Variables are not passed in the email template - laravel

I'm having this method in my controller
public function update(UserUpdateRequest $request)
{
$request->user()->update([
'name' => $request->username,
]);
Mail::to($request->user())->send(
new UserUpdated( $request->user() )
);
return redirect()->route('account.index');
}
So when the user updates the username an email is send
public $user;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->markdown('emails.user.updated');
}
And this is the email template
Hi {{ $user->username }},
We would like to inform you that your username has been updated successfully.
If this action wasn't done by you, you need to contact with our support.
But this is throwing an exception in the queues
ErrorException: Undefined variable: user in /storage/framework/views/
Any ideas what I'm doing wrong?

Try passing it to the view via with method and make user variable protected:
protected $user;
public function build()
{
return $this->view('emails.user.updated')->with(['username' => $this->user->username]);
}
And then you can access it like {{ $username }} in your view.

Try this and then access the $user in your view
public function update(UserUpdateRequest $request)
{
$request->user()->update([
'name' => $request->username,
]);
$user = $request->user();
Mail::to($request->user())
->send(new UserUpdated($user));
return redirect()->route('account.index');
}
You can't send $request directly to you email template may this is the reason why you are not able to access the $user

Related

Argument 1 passed to Illuminate\Auth\SessionGuard::attempt() must be of the type array, object given, called in

I have the controllers below to allow the user login with laravel auth system but when the user clicks in the button "Login" I get the following error:
Argument 1 passed to Illuminate\Auth\SessionGuard::attempt() must be of the type array, object given, called in C:\laragon\www\AGRIAPP\projet investisseur\AgriApp_Investor\AgriAppInvestor\vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php on line 82
When I refresh the page I log in so I wanted to solve this problem
According to the documentation, the attempt function takes an array and a bool
LoginController.php
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function showLoginForm()
{
return view('auth.login');
}
protected function credentials(Request $request)
{
$credentials = array(
'slug' => $request->slug,
'password' => $request->password,
'statut' => 1,
);
if(Auth::attempt( $credentials,false ))
{
return Redirect::to( '/admin/home' );
}
}
public function username()
{
return 'slug';
}
protected function authenticated()
{
$user = auth()->user();
$user->online = true;
$user->save();
if ($user->rule->pluck( 'name' )->contains( 'abonne' )) {
return Redirect::to( '/admin-dashboard' );
}
return Redirect::to( '/admin/home' );
}
public function logout()
{
$user = Auth::user();
$user->online=false;
$user->save();
Auth::logout();
return redirect('/');
}}
AuthController.php
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->filled('remember')
);
}
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(Request $request)
{
return $request->only($this->username(), 'password');
}
You have overridden the credentials() method but you're not returning anything from it.
Change your credentials method to:
protected function credentials(Request $request)
{
return [
'slug' => $request->slug,
'password' => $request->password,
'statut' => 1,
];
}
I realise that you were trying to authenticate the user inside the credentials method but you don't need to as, in this case, the method calling it is doing the same.
The reason your redirect didn't work either is because the calling method wasn't returning it, so your user was getting logged in but you were actually passing the redirect response to the attempt method which is what caused your error.
Also, I'm not sure if statut is a typo or not?
If you're using laravel 8+ all you have to do is to modify your credential function
protected function credentials(Request $request)
{
if(Auth::attempt($request->all())) {
return Redirect::to( '/admin/home' );
}
}

Laravel 5.5 mail with username in it

I think I miss something really simple here, but I have a script like this:
\Mail::to( User::all() )
->send( new NotificationEmail($notification) );
class NotificationEmail extends Mailable {
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #param Notification $notification
*
*/
public function __construct( Notification $notification ) {
$this->notification = $notification;
}
/**
* Build the message.
*
* #return $this
*/
public function build() {
$notification = $this->notification;
return $this
->from( [
'address' => \env( 'MAIL_DEFAULT_SENDER' ),
'name' => \env( 'APP_NAME' )
] )
->view( 'email.notification.ready' );
}
}
Now I'd like the email message to start with something like
Dear {firstname of the user}
But I have no idea how to get the firstname of user who is going to get that email. Is there any way to figure that out?
It is not a recommended way to send a email to all users, because who receive the email can see all the recipients and, they receive the same message that you cannot customize to add first name of the user.
You need to create separate Mailable to each user and queue all the Mailable. Sending email to all users separately is time-consuming task, workers are need to process the queue in background.
$users = User::all();
foreach ($users as $user) {
Mail::to($user)->queue(new NotificationEmail($notification, $user));
}
And now you can pass the $user instance, and first name of the user is available on the view:
public function __construct( Notification $notification , User $user) {
$this->notification = $notification;
$this->user = $user;
}
public function build() {
$notification = $this->notification;
return $this
->from( [
'address' => \env( 'MAIL_DEFAULT_SENDER' ),
'name' => \env( 'APP_NAME' )
] )
->view( 'email.notification.ready' , [
'user' => $this->user
]);
}

Checking if User is activated before sending Password Reset email using Forgot Password

I'm creating a small app using Laravel 5.3. I've applied user activation (via email confirmation) on Laravel's default Auth. But i couldn't find a way to stop sending password reset link if account/user not activated by verifying email address. Currently if a user creates an account and doesn't verify the email address he/she can login using Password Reset link.
this what i've in user table
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->nullable();;
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('company')->nullable();;
$table->string('password');
$table->boolean('activated')->default(false);
$table->rememberToken();
$table->timestamps();
});
Schema::create('user_activations', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->string('token')->index();
$table->timestamp('created_at');
});
}
UPDATE
I tried to do it by updating the below function. but it's not working
public function reset(Request $request)
{
if (!$request->activated) {
return redirect('/');
} else {
$this->validate($request, $this->rules(), $this->validationErrorMessages());
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
}
);
return $response == Password::PASSWORD_RESET
? $this->sendResetResponse($response)
: $this->sendResetFailedResponse($request, $response);
}
}
I found the solution. Just in case if someone looking for the same solution. Here is the function i overridden
public function sendResetLinkEmail(Request $request)
{
$this->validate($request, ['email' => 'required|email']);
$user_check = User::where('email', $request->email)->first();
if (!$user_check->activated) {
return back()->with('status', 'Your account is not activated. Please activate it first.');
} else {
$response = $this->broker()->sendResetLink(
$request->only('email')
);
if ($response === Password::RESET_LINK_SENT) {
return back()->with('status', trans($response));
}
return back()->withErrors(
['email' => trans($response)]
);
}
}
Another solution is to overwrite the sendPasswordResetNotification in your User Model:
/**
* OVERWRITE ORIGINAL
* #param string $token
*/
public function sendPasswordResetNotification($token) {
if(!$this->active){
session()->flash('error', 'Your account is disabled.');
return back();
}
$this->notify(new \Illuminate\Auth\Notifications\ResetPassword($token));
}
If the user is not activated, he won't get another email. Instead, he will be returned back to the login page with an error message in the session. To show it you need something like this in your blade file:
#if ($errors->any())
#foreach ($errors->all() as $message)
<div class="alert alert-danger-plain">
<i class="icon-exclamation"></i> {{ $message }}
</div>
#endforeach
#endif
Another straightforward way is to create a new validation rule to check if the user account is activated, And then add the rule to the validateEmail method inside the ForgotPasswordController. Just make sure that you delete the password token everytime you deactivate a user.
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use App\User;
class ActiveUser implements Rule
{
/**
* Create a new rule instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
$user = User::whereEmail($value)->first();
if($user) {
if($user->active) {
return true;
}
return false;
}
return true;
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'Your account is deactivated.';
}
}
And in the ForgotPasswordController
/**
* Validate the email for the given request.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function validateEmail(Request $request)
{
$this->validate($request, ['email' => [ 'required', 'email', new ActiveUser ]]);
}
And this is how to delete the token at any user deactivation.
$user = \App\user::find(1);
\Illuminate\Support\Facades\Password::broker()->deleteToken($user);

Display Errors in Laravel Built in Auth with confirmed field Laravel 5.3

I'm having problems with this Authentication with confirmed specifically how to display the errors. That says "It is in active". The code works and the user can't login but there is no error. How I'm going to do it?
class LoginController extends Controller
{
use AuthenticatesUsers;
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(\Illuminate\Http\Request $request)
{
$credentials = $request->only($this->username(), 'password');
return array_add($credentials, 'active', '1');
}
Inside RegistersUsers trait there is a function
protected function registered(Request $request, $user)
{
if(!$user->active){
// store msg in session and display to user
Auth::logout();
}
}
Similarly
in AuthenticatesUsers there is a function
protected function authenticated(Request $request, $user)
{
if(!$user->active){
//store msg in session and display to user
Auth::logout();
}
}
Try like this:
add on your class of controller
use app\User;
CONTROLLER
protected function credentials(\Illuminate\Http\Request $request)
{
$credentials = $request->only($this->username(), 'password');
$user_active = User::where('username', $request->username)->first();
if ($user_active->active != 1){
return 'error';
}else{
return array_add($credentials, 'active', '1');
}
}
You can insert a validation for user that have "active" = 1, if user that is tryng to login and not is actived it return a error. Please try it and let me kknow if for user not actived return error, if it work i will update my question with messagge error "user not actived" in the view.

Laravel Trying to get property of non-object

I am struggling to understand how laravel works and I have a very difficult time with it
Model - User.php the User model
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $fillable = array('email' , 'username' , 'password', 'code');
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password');
public function Characters()
{
return $this->hasMany('Character');
}
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->getKey();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password;
}
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail()
{
return $this->email;
}
}
Model - Character.php the character model
<?php
class Character extends Eloquent {
protected $table = 'characters';
protected $fillable = array('lord_id','char_name', 'char_dynasty', 'picture');
public function user()
{
return $this->belongsTo('User');
}
public function Titles()
{
return $this->hasMany('Title');
}
}
?>
routes.php
Route::group(array('prefix' => 'user'), function()
{
Route::get("/{user}", array(
'as' => 'user-profile',
'uses' => 'ProfileController#user'));
});
ProfileController.php
<?php
class ProfileController extends BaseController{
public function user($user) {
$user = User::where('username', '=', Session::get('theuser') );
$char = DB::table('characters')
->join('users', function($join)
{
$join->on('users.id', '=', 'characters.user_id')
->where('characters.id', '=', 'characters.lord_id');
})
->get();
if($user->count()) {
$user = $user->first();
return View::make('layout.profile')
->with('user', $user)
->with('char', $char);
}
return App::abort(404);
}
}
In my code I will redirect to this route with the following:
return Redirect::route('user-profile', Session::get('theuser'));
In the view I just want to do:
Welcome back, {{ $user->username }}, your main character is {{ $char->char_name }}
My problem is that I will receive this error: Trying to get property of non-object in my view. I am sure it is referring to $char->char_name. What's going wrong? I have a very difficult time understanding Laravel. I don't know why. Thanks in advance!
You should be using the Auth class to get the session information for the logged in user.
$user = Auth::user();
$welcome_message = "Welcome back, $user->username, your main character is $user->Character->char_name";
You don't need to pass anything to that route either. Simply check if the user is logged in then retrieve the data. You have access to this data from anywhere in your application.
if (Auth::check())
{
//the user is logged in
$user = Auth::user();
To answer your question in the comments, reading the documentation would solve all of these problems, however:
public function user()
{
if (Auth::check())
{
$user = Auth::user();
return View::make('rtfm', compact('user'));
}
else
{
return "The documentation explains all of this very clearly.";
}
}

Resources