Passing data with login redirect - Laravel 4 - laravel

The scenario is, a user must be logged in to be able to 'book an event'. My ideal process is:
User wishes to attend an event, clicks the attend button.
Auth filter realises user isn't logged in and so redirects to the login page
Once user is authenticated, the event ID and user ID is passed to the 'PostCreate' function within the 'Events' controller to book them on.
Currently, the user is redirected if not logged in, to the login page. Once the user is logged in, it attempts to call the 'events/create' controller method which is postCreate, but an error message is presented.
Symfony \ Component \ HttpKernel \ Exception \ NotFoundHttpException
Controller method not found.
However, as I am now authenticated, I can go back to the event, click attend, and it will process the booking. I am a little stumped as to why this won't work! Any help would be appreciated.
Is it down to the event ID not being passed with the login data? If so, it still should be able to find the controller method?
Event Controller:
<?php
class EventsController extends BaseController {
protected $layout = "layouts.main";
public function __construct(){
$this->beforeFilter('csrf', array('on'=>'post'));
$this->beforeFilter('auth', array('only'=>array('postCreate')));
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function postCreate(){
$user_id = Auth::user()->id;
$user = myApp\User::find($user_id);
$event_id = Input::get('event_id');
$event_name = myApp\Event::find($event_id)->title;
$user->event()->attach($event_id);
return Redirect::back()->with('message-success', 'You are now attending '.$event_name.' !');
}
Users Controller
public function postSignin(){
if (Auth::attempt(array('email'=>Input::get('email'), 'password'=>Input::get('password')))) {
$title = Auth::user()->title;
$surname = Auth::user()->surname;
return Redirect::intended('users/dashboard')->with('message-success', 'You are now logged in, '.$title.' '.$surname.'. ');
} else {
return Redirect::to('users/login')
->with('message-danger', 'Your username/password combination was incorrect')
->withInput();
}
}
Show.blade.php
<div class="col-md-3">
#if (Auth::user())
<br>
#if (!in_array($events->id, $attending))
{{ Form::open(array('url'=>'events/create', 'class'=>'form-signup', 'role'=>'form')) }}
{{ Form::hidden('event_id', $events->id) }}
{{ Form::submit('Attend Event', array('class'=>'btn btn-success'))}}
{{ Form::close() }}
#else
{{ Form::open(array('url'=>'events/cancel', 'class'=>'form-cancel', 'role'=>'form')) }}
{{ Form::hidden('event_id', $events->id) }}
{{ Form::submit('Cancel Booking', array('class'=>'btn btn-warning'))}}
{{ Form::close() }}
#endif
#else
{{ Form::open(array('url'=>'events/create', 'class'=>'form-signup', 'role'=>'form')) }}
{{ Form::hidden('event_id', $events->id) }}
{{ Form::submit('Attend Event', array('class'=>'btn btn-success'))}}
{{ Form::close() }}
#endif
</div>
Routes
/* Event Route */
Route::get('events/{id}/{slug}', 'EventsController#show');
Route::controller('events', 'EventsController');
/* User Route */
Route::controller('users', 'UsersController');
/* Home Route */
Route::get('/', 'HomeController#getHome');
Route::controller('/', 'HomeController');

All Redirect responses will create a GET request. Your route and controller setup would then be looking for getCreate() instead of postCreate(), hence the error.

Related

Method Illuminate\Database\Eloquent\Collection::links does not exist

I created a model relationship between User and Message. I want to implement a list of messages for the authenticated user but I get the following error.
Method Illuminate\Database\Eloquent\Collection::links does not exist
Controller
public function index()
{
$user_id = auth()->user()->id;
$user = User::find($user_id);
return view('message.index')->with('messages', $user->message);
}
Message provider
class message extends Model
{
public function user() {
return $this->belongsTo('App\User');
}
}
User provider
public function message ()
{
return $this->hasMany('App\Message');
}
index.blade.php
#extends('layouts.app')
#section('content')
<h1>messages</h1>
#if(count($messages)>0)
#foreach ($messages as $message)
<div class="well">
<h3>{{$message->user}}</h3>
<small>Written on {{$message->created_at}} </small>
</div>
#endforeach
{{$messages->links()}}
#else
<p> no post found </p>
#endif
#endsection
Error
"Method Illuminate\Database\Eloquent\Collection::links does not exist.(View: C:\xampp\htdocs\basicwebsite\resources\views\message\index.blade.php)"
Check your view blade, that method (links()) only could be used when your data model is implementing paginate() method.
If you dont use paginate(), remove this part:
{{$messages->links() }}
If you are trying to paginate your data when it gets to the view then you need to add the paginate in your controller before passing the data to the view. Example
return $users = Users::select('id','name')->paginate(10);
with that paginate method in your controller, you can call the links method to paginate your object in view as shown below
{{$users->links()}}
hope it helps you
There are 2 ways to resolve this issue:
Either use paginate function while searching data from database:
$users = DB::table('users')->where('id',$user_id)->paginate(1);
Remove links() function from index.blade.php
{{ $messages->links() }}
Remove {{ $messages->links() }} to in your index.blade.php because {{ $messages->links() }} is supported only when you use paginate
You can do something like this in your controller file.
public function index()
{
$messages = Message::all()->paginate(5);
$user_id = auth()->user()->id;
$user = User::find($user_id);
return view('message.index')->with('messages', $messages, $user->message);
}

How to output message after form submit on the same page?

When a user sumbit a form I need to output message for him on the same page.
When I submit a form the page refreshes, handler fires (php function), some POST data inserts into database, I set $this['success'] = 1 and then check with Twig:
{% if success %}
here is many tags with information and a message
{% else %}
here is a form
{% endif %}
But if I press F5 the form is resubmitting, the insert query executes again.
Do this request with AJAX isn't a real option.
There are numerous ways to answer this question (use Cache, database, cookies, session). This is really easy using Session Flashing or in this instance I am going to show you how to do it with Returning a redirect with flash data.
Spin up a CMS Page
Place HTML Form code: *Note the {{ something }} is important to show our response after submitting the form. This request does not use AJAX.
{{ something }}
{{ form_open({ request: 'onSubmit', class: 'row', autocomplete: 'off' }) }}
{{ form_input('text', 'something', '', { class: 'input padding' }) }}
{{ form_submit('Submit', { class: 'button padding' } ) }}
{{ form_close() }}
PHP code:
function onStart() {
$something = Session::get('something');
$this['something'] = $something;
}
function onSubmit() {
$something = Input::get('something');
return Redirect::refresh()->with('something', $something);
}
Test and enjoy one way to create a message after submitting a form.
If you are using laravel then you can easily implement to handle this functionality
In View file you need to write this code, which will display message on the same page where you are displaying form.
file.blade.php file
#if(Session::has('success'))
<div class="alert alert-success">
{{ Session::get('success') }}
</div>
#endif
FormController.php
public function addUser(Request $request){
User::create([
'name' => $request->name,
'email' => $request->email,
'gender' => $request->gender,
'contact' => $request->contact,
.....]);
//below code help to display the message that you want on same page whereuser entered data
return back()->with('success', 'Thanks you for adding!!');
}
return back()->with('success', 'Thanks you for adding!!');
use this code for laravel project to display message on same page

Laravel send email to address from database

In my index view I show all the users and there is a button that will change the user status to active and not active. The code looks like this:
#foreach($users as $user)
<tr>
<td>{{$user->name}}</td>
<td>{{$user->surname}}</td>
<td>{{$user->email}}</td>
<td>
#if($user->is_active == 0)
{!! Form::model($user, ['method' => 'PUT', 'action'=>['AdminUserController#activateuser', $user->id]]) !!}
{!! Form::submit('Activate', ['class'=>'btn btn-primary']) !!}
{!! Form::close() !!}
#else
{!! Form::model($user, ['method' => 'PUT', 'action'=>['AdminUserController#activateuser', $user->id]]) !!}
{!! Form::submit('De-Activate', ['class'=>'btn btn-danger']) !!}
{!! Form::close() !!}
#endif
</td>
<td>{{$user->cell}}</td>
<td><button class="btn btn-primary">View Property</button></td>
<td><button class="btn btn-danger">Delete</button></td>
</tr>
#endforeach
So when I click on activate/deactivate button I trigger my activateuser function of the controller. After activation, an email is sent.
The controller looks like this:
public function activateuser(Request $request, $id){
$user = User::findOrFail($id);
if($user->is_active == 0){
$user->update([$user->is_active = 1]);
Mail::send(new activateUser());
}
else{
$user->update([$user->is_active = 0]);
}
return redirect()->back();
}
At the moment the email is going to myself and my Mailabçe looks like this:
public function build()
{
return $this->view('emails.activateuser')->to('wosleybago#gmail.com');
}
What I want instead is to send the email to the email address from the user email in the database table.
How can I do that?
So, someho I should get the $user->email
I usually want my emails have all the information in itself, so I pass User instance or whatever instance that holds data required to compose the mail.
So the Mailable has __construct(..) like this:
/**
* #var \App\User
*/
public $user; // since this is a public property its going to be available in view of mailable as $user
__construct(App\User $user) {
$this->user = $user;
// further more I set the to(), this is what you are after
$this->to($user->email, $user->name);
// and subject
$this->subject('You are activated!');
}
...
And now all you need to do in the controller is the following:
Mail::send(new activateUser($user));
As mentioned above, $user is available in the mail-view so you can use it there as well:
Hi, {{ $user->name }},
...
Note: change the activateUser to ActivateUser to follow PSR-2
Class names MUST be declared in StudlyCaps.
I also use queued mails so I set the $timeout and $tries properties right on the Mailable class.
Sending email is described in Doc: https://laravel.com/docs/5.6/mail#sending-mail
Put this code inside activateUser() function
Mail::to($user)->send(new YourMailableName());
Do not forget to import Mail and YourMailableName using "use" keyword.
Or you can use user email instead object
Mail::to($user->email)->send(new YourMailableName());
And remove ->to('wosleybago#gmail.com') from your Mailable/
You should pass User Email in when creating new activateUser instance, like so
Mail::send(new activateUser($user->email));
And then use this attribute later.
Sending Email to particular a person is quite simple. My suggestion would be as follows:
Use Queue to send mail later as it will take some time to respond from controller to view.
In existing code you can get the email of the current user and send it using a helper to() that comes with mail functionality of laravel.
You can code it like this.
if($user->is_active == 0){
$user->update([$user->is_active = 1]);
Mail::to($user->email)->send(new MailableClassInstance);
}

Laravel email resulting in view not found error

I am firing an event that sends an email to the user when he requests a password reset.
Here's the event listener that will send an email
class SendResetPasswordLink {
public function handle(UserForgotPassword $event) {
Mail::to($event->user)
->queue(new SendResetPasswordToken($event->user->passwordResetToken));
}
}
Here's my mail class:
class SendResetPasswordToken extends Mailable {
use Queueable, SerializesModels;
public $token;
public function __construct(PasswordReset $token) {
$this->token = $token;
}
public function build() {
return $this->subject('Reset your MyEngine password')
->markdown('emails.password.reset')
->text('emails.password.reset_text');
}
}
I have email files (both html and text) available at
resources/views/emails/password/reset.blade.php
and
resources/views/emails/password/reset_text.blade.php
It is not working and I am getting the following error:
"View [] not found. (View: /home/vagrant/Laravel/youtube/resources/views/emails/password/reset.blade.php)"
What do I need to do? All my blade files are in place.
Here's my reset.blade.php
#component('mail::message')
<strong>Hello {{ $token->user->getFirstNameOrUserName() }}!</strong>
You are receiving this email because we received a password reset request for your account.
If you did not request a password reset, no further action is required.
#component('mail::button', [
'url' => route('password.reset', ['token' => $token,]) . '?email=' . urlencode($token->user->email)
])
Reset Password
#endcomponent
Thanks,<br>
{{ config('app.name') }}
#endcomponent
<hr>
If you’re having trouble clicking the <strong>"Reset Password"</strong> button, copy and paste the URL below into your web browser:<br>
<small>{{ route('password.reset', ['token' => $token,]) . '?email=' . urlencode($token->user->email) }}</small>
#endcomponent
I found the answer,
For whatever reason I had closed(ended) the markdown component twice #endcomponent.

Laravel 4 MethodNotAllowedhttpException

I am get a MethodNotAllowedHttpException when I submit the form detailed below. The route appears correct to me and is syntactically the same as other post routes that are working just fine. The controller method exists but even so I think the exception is occuring before the request gets to the controller as item 4 on the left of the laravel error page says handleRoutingException right after item 3 which says findRoute. I am pretty sure I am not using restful routing the way you should in laravel 4 but that is because the tutorial I am following a laravel 3 tutorial and updating hte syntax to 4 as I go but like I said the other routes work fine so I can't figure out why this one isn't.
Template
#extends('layouts.default')
#section('content')
<div id="ask">
<h1>Ask a Question</h1>
#if(Auth::check())
#include('_partials.errors')
{{ Form::open(array('ask', 'POST')) }}
{{ Form::token() }}
<p>
{{ Form::label('question', 'Question') }}
{{ Form::text('question', Input::old('question')) }}
{{ Form::submit('Ask a Question') }}
</p>
{{ Form::close() }}
#else
<p>
<p>Please login to ask or answer questions.</p>
</p>
#endif
</div><!-- end ask -->
#stop
Route
Route::post('ask', array('before'=>'csrf', 'uses'=>'QuestionsController#post_create'));
Controller
<?php
class QuestionsController extends BaseController {
public $restful = true;
protected $layout = 'layouts.default';
public function __construct()
{
$this->beforeFilter('auth', array('post_create'));
}
public function get_index() {
return View::make('questions.index')
->with('title', 'Make It Snappy Q&A - Home');
}
public function post_create()
{
$validation = Question::validate(Input::all());
if($validation->passes()) {
Question::create(array(
'question'=>Input::get('question'),
'user_id'=>Auth::user()->id
));
return Redirect::Route('home')
->with('message', 'Your question has been posted.');
} else {
return Redirect::Route('register')->withErrors($validation)->withInput();
}
}
}
?>
I believe defining public $restful = true; is how it was done in Laravel 3. In Laravel 4 you define a restful controller in your routes like so:
Route::controller('ask', 'QuestionsController');
Then to define the functions you would not use an underscore to separate them. You must use camel case like so:
public function getIndex()
{
// go buck wild...
}
public function postCreate()
{
// do what you do...
}
For RESTful Controllers you should define the route using Route::controller method, i.e.
Route::controller('ask', 'QuestionsController');
and controller methods should be prefixed with http verb that it responbds to, for example, you may use postCreate and you have post_create instead, so it doesn't look like a Restful controller.
You are using public $restful = true; in your controller, this is not being used in Laravel-4, and public $restful = true; may causing the problem, so remove this line.

Resources