Laravel 5.5 - Send Email - Can't Get Property On Non-Object - laravel

I am trying to send email from a Laravel 5.5 controller like this...
$user = User::find(1)->toArray();
Mail::send('emails.invite', $user, function($message) use ($user) {
$message->to($user->email);
$message->from('me#example.com');
$message->subject('Test Subject');
});
This fails with the error...
"message": "Trying to get property of non-object",
If I echo the array into the subject I can see that I do have the correct $user available to me, but for some reason it doesn't like it when I try and extract $user->email
Anyone any ideas?

You're calling ->toArray() on the User object and so it is no longer an object!
$user = User::find(1); // Assuming you are already protecting yourself from potentially not finding a user
$viewData = $user->toArray(); // Or better still don't expose the underlying structure
Mail::send('emails.invite', $viewData, function($message) use ($user) {
$message->to($user->email);
$message->from('me#example.com');
$message->subject('Test Subject');
});

Your $user is type ofarray not object as you expected, because of toArray() called on returned model. Either change that line and remove said toArray() to keep it unchanged object, or make this line:
$message->to($user->email);
look more like:
$message->to($user['email']);
with proper array element reference.

Related

Laravel validation couldn't store value after validate and give error 500

I have a form that using ajax for update data client. In that form there is an input file. Everything is going fine except for updating the file. File is sent, it changed on storage too, but it gives error on validation and didn't change data on database.
Here is the code on the controller :
public function update(Request $request, Client $client)
{
$validatedData = Validator::make($request->all(), [
'name' => 'required|max:255',
'logo'=> 'image|file|max:100',
'level' => 'required|max:1'
]);
$validatedData['user_id'] = auth()->user()->id;
if ($validatedData->fails()){
return response()->json($validatedData->errors());
} else {
if($request->file('logo')){
if($request->oldLogo){
Storage::delete($request->oldLogo);
}
$validatedData['logo'] = $request->file('logo')->store('logo-clients');
}
$validateFix = $validatedData->validate();
Client::where('id', $client->id)->update($validateFix);
return response()->json([
'success' => 'Success!'
]);
}
}
It gives error on line :
$validatedData['logo'] = $request->file('logo')->store('logo-clients');
With message :
"Cannot use object of type Illuminate\Validation\Validator as array"
I use the same code that works on another case, the difference is the other not using ajax or I didn't use Validator::make on file input. I guess it's just wrong syntax but I don't really know where and what it is.
To retrieve the validated input of a Validator, use the validated() function like so:
$validated = $validator->validated();
Docs:
https://laravel.com/docs/9.x/validation#manually-creating-validators
https://laravel.com/api/9.x/Illuminate/Contracts/Validation/Validator.html
$validatedData is an object of type Illuminate\Validation\Validator.
I would say the error is earlier there as well as this line should give an error also:
$validatedData['user_id'] = auth()->user()->id;
As ericmp said, you first need to retrieve the validateddata to an array and then work with it.

Undefined variable inside Laravel view when using Mail

While trying to send verification email using Laravel 5.2, I get an error:
Undefined variable: confirmation_code (View:
C:\xampp\htdocs\laravel\resources\views\email\verify.blade.php)
My code looks like this:
Controller.php:
public function postSignup(Request $request){
$this->validate($request,[
'email'=>'required|unique:users|email',
'name'=>'required|max:50|min:3',
'password'=>'required|min:6',
'con-password'=>'required|same:password',
]);
$confirmation_code=['code'=>str_random(20)];
$name = $request->input('name');
Mail::send('email.verify',$confirmation_code,function($message)
use($request,$name){
$message->to($request->input('email'),$name)
->subject('Verify Your Email Address');
});
User::create([
'email'=>$request->input('email'),
'name'=>$request->input('name'),
'password'=>bcrypt($request->input('password'))
]);
return redirect()->back()->with('info','Congratulation you have been successfully registered.Please check your email for verification');
}
Mail.verify.blade.php:
<h2>Verify Your Email Address</h2>
<div>
Thanks for creating an account with the verification demo app.
Please follow the link below to verify your email address
{{ URL::to('register/verify/'.$confirmation_code) }}.<br/>
</div>
</body>
Try this:
Mail::send('email.verify', compact('confirmation_code'), function ($message) use($request, $name) {
$message->to($request->input('email'),$name)
->subject('Verify Your Email Address');
});
The reason why it fails is that Laravel views accept an associative array as their data, so that it can turn them into variables using keys as variables names and match them to their corresponding values.
What compact does is turn your variable into an associative array, with the name of the variable as its key (sort of the opposite of what the Laravel view will do).

Laravel password recovery template

I have the following code which sends a passowrds recovery mail:
public function recovery(Request $request)
{
$validator = Validator::make($request->only('email'), [
'email' => 'required'
]);
if($validator->fails()) {
throw new ValidationHttpException($validator->errors()->all());
}
$response = Password::sendResetLink($request->only('email'), function (Message $message) {
$message->subject(Config::get('boilerplate.recovery_email_subject'));
});
switch ($response) {
case Password::RESET_LINK_SENT:
return $this->response->noContent();
case Password::INVALID_USER:
return $this->response->errorNotFound();
}
}
Which I found out uses the following template: resources/views/auth/emails/password.php
which is an empty file.
How I can access the token from this template?
Isn't there any built-in view to use from laravel?
The function in your questions doesn't return a view.
Also, I'm unfamiliar with that path to the view that is in your question. Which version of Laravel are you using?
Anyhow, you can get the reset token from the DB, just like any other value in the DB. E.g. from a controller that is returning a view:
$user = User::find(Auth::id());
$remeber_token = $user->remember_token;
return view('to_your_view.blade.php', compact('remember_token');
And then in the view file:
{{ $remember_token }}
This will output it, no need to use echo or anything.
But, again, the function you pasted into your question is not a function that is returning a view, so I'm not sure where to tell you to put the above code.
As for your questoin about Laravel having an in-built view for 'this', in Laravel 5.3, at least, the view I assume you want will be within `resources/views/auth/passwords/'.

Get recipient name on view in laravel mail

I have a set of recipients. I am able to send mail to all of them. But how to get their name on the view. To be specific how to get $user value in my view(emails.test).
Mail::send('emails.test', ['data' => $data], function ($message) use ($data) {
foreach($data['users'] as $user) {
$message->to($user->email, $name = $user->firstName . ' ' . $user->lastName);
}
$message->subject('test');
});
Is there any way to access $user value in my view? I can access $data in my view. $data['users'] is an array of users. I need particular/current User's name in the view.
My view(emails.test)
<div>Dear {{$user->firstName}},</div>
How are you?....
But user is undefined here.
Thanks in advance.
Debabrata
from the docs
The send method accepts three arguments. First, the name of a view
that contains the e-mail message. Secondly, an array of data you wish
to pass to the view. Lastly, a Closure callback which receives a
message instance, allowing you to customize the recipients, subject,
and other aspects of the mail message
as you can see the second arguments its the data you send to the view
so in your view you can use the $data array just like you did inside the closure:
#foreach($data['users'] as $user) {
{{$user->username}}
}

Pass value to URL - REST style

<h1>Edit page of {{ $user->username }}</h1>
{{ Form::open(['route' => 'user.store']) }}
... the rest of the view
This is in my login view. The related code in the store method in the controller looks like this:
if (Auth::attempt(Input::only('username', 'password'))) {
$user = Auth::user();
return Redirect::route('user.show', ['user' => $user]);
}
and the show method:
public function show($user)
{
return View::make('user.edit', ['user' => $user]);
}
And I get .../user/%7Buser%7D as URL (and I want it to be, eg. .../user/exampleusername) and also an exception: ErrorException: Trying to get property of non-object.
When I dd($user) in the show method (or in the view, doesn't matter), I get simply string[6] {user}, which means I do not pass the $user successfully to the user.show route.
The official docs give this example: return Redirect::route('profile', array('user' => 1)); which seems relevant to my case, which I think should look like this in my code: return Redirect::route('user.show', ['user' => $user]);?
Funny, though, if in the show method I try to take the user object from the session (Auth::user()), and dump it, as here:
public function show($user)
{
$user = Auth::user();
dd($user);
...
it will still be NULL, but if I dump it in the index method:
public function index()
{
if (Auth::check()) {
dd(Auth::user());
...
, then it returns correct object, full of parameters and values... I have no idea what's going on and why in one method I have the session object, but in the other I don't.
Any suggestions on how to go around this problem?
UPDATE: I narrowed it down to this implementation in the store method:
return Redirect::route('user.show')->with('user', $user);
and in the show method:
$user = Session::get('user');
return View::make('user.edit', ['user' => $user]);
Because apparently the only place where you can pass an array that will explode into single variables is in View::make, whereas in Redirect::to, Redirect::action and Redirect::route, etc., you must use the ->with('key', $value) function. Those values then will be available in the Session singleton.
Nevertheless, I still get .../%7Buser%7D in the URL. And I don't know how to get out of this...
You need to pass the id of the user to the user.show route - not the $user itself.
return Redirect::route('user.show', [$user->id]);

Resources