Laravel Notification - Call to a member function routeNotificationFor() on string - php

Laravel 5.5
Controller
public function sendBookingSms(){
$checkState = session()->get('checkState');
$staffs = Staff::whereIn('staffId',$checkState)->get();
foreach ($staffs as $staff) {
$email = str_replace(" ","","44".substr($staff->mobile, 1)).'#mail.mightytext.net';
Notification::send($email, new NewBooking($email));
}
return $staffs;
session()->forget('checkState');
return redirect(route('booking.current'))->with('message','Succesfully Send SMS to selected staffs !!');
}
NewBooking.php (Notification)
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', url('/'))
->line('Thank you for using our application!');
}
When calling this controller I am getting this error.
$staffs.
{
"staffId":45,
"forname":"Eldhose",
"surname":"John",
"categoryId":2,
"email":"devhelloworld#gmail.com",
"mobile":"07588593278",
"whatsappNumber":"57656578658",
"gender":1,
"address":"Poole",
"pincode":null,
"modeOfTransport":1,
"pickupLocation":"Office",
"branchId":0,
"zoneId":1,
"bandId":1,
"paymentMode":1,
"payRateWeekday":10,
"payRateWeekNight":20,
"payRateWeekendDay":10,
"payRateWeekendNight":20,
"payRateSpecialBhday":11,
"payRateSpecialBhnight":15,
"payRateBhday":11,
"payRateBhnight":15,
"status":1,
"deleted_at":null,
"created_at":"2018-02-26 22:16:44",
"updated_at":"2018-02-26 22:16:44"
}
Please help me on this.... Thanks

Notification::send() requires the first argument to be an object, usually one that uses the Notifiable trait. You pass just a string holding email address, hence the error.
If you simply want to send a notification to given email address, you'll need to use on-demand notifications. The following should do the trick:
Notification::route('mail', $email)->notify(new NewBooking($email));
For more details see the docs: https://laravel.com/docs/5.6/notifications#sending-notifications
Latest docs: https://laravel.com/docs/9.x/notifications#on-demand-notifications

Related

Slack Notifications in Laravel - to() function not doing anything?

I am trying to send notifications to individual users with laravel 6 using the documentation here: https://laravel.com/docs/6.x/notifications#slack-notifications
My from and to functions don't seem to be doing anything.
// call notification
Notification::route('slack', $slackUrl)->notify(new notifyHours($event->user));
App\Notifications\notifyHours
// send DM
public function toSlack($notifiable)
{
return (new SlackMessage())
->from('Puffin', ':puffin:') // doesn't seem to do anything
->to('#U4KFXXXXX') // doesn't seem to do anything
->image('https://XXX.png')
->content("Hi! Make sure I am up to date!")
->attachment(function(SlackAttachment $attachment) use ($notifiable) {
$attachment->title('Your Hours', 'https://xxx/tasks')
->fields([
'Today' => $this->hours->today.' hours',
'This Week' => 'You worked '.$this->hours->week. ' hours.'
]);
});
}
How come the notification is sent to an entire channel, instead of the user I define in the to() function?
According to the code the to() method only accepts a channel not a user of that team.
/**
* Set the Slack channel the message should be sent to.
*
* #param string $channel
* #return $this
*/
public function to($channel)
{
$this->channel = $channel;
return $this;
}

notification on new user registration

I used two tutorials to create code which notifies me on a new user registration. mail-notifications and redirect-login-register-add-method/
This works now
I am just sending a notification to default email defined here in my User model:
This is my desired goal
I want to send newly registered user's email in the emailed notification. Also, I wish to customize recipient for this specific HelloUser notification.
public function routeNotificationForMail()
{
return 'name#gmail.com';
}
The notification is fired by the code in my RegisterController.php:
protected function redirectTo()
{
$user = Auth::user();
$user->notify(new \App\Notifications\HelloUser());
return '/'; // redirects to main page
}
The above solution works, but I after many attempts I am still unable to get these extended result:
to do 1
I will have several notifications, which I want to mail to 2-3 emails, not just one.
My attempt
In my notification file App\Notifications\\HelloUser.php I tried to add
extra line. (Note tha the line is now commented)
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', url('/'))
->line('The new user email is ');
// ->to('name#gmail.com');
}
... but I failed. I could define global recipient as described here in the documentation
My question #1
How I can I define a separate recipient for each Notification?
TO DO 2
I also tried to get the newly registered user's email into the emailed notification.
For this purpose I tried to copy my solution from Mailables. So in RegisterControler.php I tried to pass $user variable in the function:
protected function redirectTo()
{
$user = Auth::user();
$user->notify(new \App\Notifications\HelloUser($user));
return '/';
}
and then in my Notification file App\Notifications\HelloUser I did this:
public $user;
public function __construct($user)
{
$email = $user->email;
}
in a hope that this piece would produce a notification with new user's email:
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', url('/'))
->line('The new user email is '.$user->email);
}
The result: I just get Undefined variable: user.
TO DO
How to make this code work?
Thank you for your time.
=============
Edit:
upon #Arun_jai request I place here the dd($notifiable). It seems that it is generated properly and the object is just instance of the User model. The relevant part:
#attributes: array:6 [▼
"name" => "Peter attempt 16"
"email" => "name#gmail.com"
"password" => "$2t9WHLFY14XNf0$nj7TYDYAxiZ/kdfrUy$1vC2"
"updated_at" => "2018-01-18 07:08:12"
"created_at" => "2018-01-18 07:08:12"
"id" => 270
]
Regarding the Undefined variable: user error, try instantiating the $user variable in your constructor, instead of the email. Your constructor should look like this:
public function __construct($user)
{
$this->user = $user;
}
Then you will be able to get the users' email by calling it with $this->user in any place of that class, so your MailMessage creation would look like this:
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', url('/'))
->line('The new user email is ' . $this->user->email);

Laravel return only the first message and only it's content

I am using Laravel 5.4, have ajax that calls a post method which calls the register controller (built in) and returns an error in json format, i want only message to be returned and only it's body:
Example:
"first_last_name":["First and last names are required"] => only "First and last names are required" to be returned.
I am fairly new to Laravel and think here its the validation:
public function register(Request $request)
{
$this->validator($request->all())->validate(); // here i tried to use ->messages and -> first, but doesn't not seem to work
event(new Registered($user = $this->create($request->all())));
// commented because i don't want auto login and redirect
//$this->guard()->login($user);
//return $this->registered($request, $user)
// ?: redirect($this->redirectPath());
}
I tried using ->messages() and ->first() but i can't seem to make it work.
Thank you
You can get every request property using the get method.
Example:
$firstName = $request->get('first_last_name');
With this you can validate every property separately.
Try this:
$validator = validator($request->all(), [
'first_last_name' => 'required',
]);
if($validator->fails()) {
return response($validator->getMessageBag()->first(), 422);
}
return response('OK', 200);

Using the ResetPassword notification email template for custom emails

I generated a new email object through the artisan command to notify users about cumulative notifications. I succeeded using a custom template through the build method of the Email object:
public function build()
{
return $this->view('email.cumulative-notifications')
->with(['amount' => $this->amount])
->subject('You have some notifications!');
}
I want to use the template that is used for the reset password email which can be filled with lines and links like the ResetPassword does:
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Reset Password')
->greeting('Hello!')
->line('...')
->action('Reset Password', url('password/reset', $this->token))
->line('...');
}
Should I use Notifications objects instead of Emails?

Testing unauthorized user restriction in Laravel PHPUnit

Laravel Version 5.2
In my project, users with role_id = 4 has the admin role and can manage users.
I have defined the following ability in AuthServiceProvider:
public function boot(GateContract $gate)
{
$this->registerPolicies($gate);
$gate->define('can-manage-users', function ($user)
{
return $user->role_id == 4;
});
}
I have used this ability in the UserController __construct method as follows:
public function __construct()
{
$this->authorize('can-manage-users');
}
In ExampleTest, I have created two tests to check if the defined authorization works.
The first test for admin user who has role_id = 4. This test passes.
public function testAdminCanManageUsers()
{
$user = Auth::loginUsingId(1);
$this->actingAs($user)
->visit('users')
->assertResponseOk();
}
The second test is for another user who does not have role_id = 4. I have tried with response status 401 and 403. But the test is failing:
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->assertResponseStatus(403);
}
First few lines of the failure message is given below:
A request to [http://localhost/users] failed. Received status code [403].
C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:196
C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:80
C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\InteractsWithPages.php:61
C:\wamp\www\laravel\blog\tests\ExampleTest.php:33
Caused by exception 'Illuminate\Auth\Access\AuthorizationException'
with message 'This action is unauthorized.' in
C:\wamp\www\laravel\blog\vendor\laravel\framework\src\Illuminate\Auth\Access\HandlesAuthorization.php:28
I have also tried to use 'see' method as follows:
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->see('This action is unauthorized.');
}
But it's failing too. What am I doing wrong? How can I make the test pass?
The mistake is calling the visit method. The visit method is in the InteractsWithPages trait. This method calls the makeRequest method which in turn calls assertPageLoaded method. This method gets the status code returned and if it gets code other than 200, it catches a PHPUnitException and throws an HttpException with the message
"A request to [{$uri}] failed. Received status code [{$status}]."
This is why the test was failing with the above message.
The test can be successfully passed by using get method instead of visit method. For example:
public function testNonAdminCannotManageUsers()
{
$user = App\User::where('role_id', '<>', 4)->first();
$this->actingAs($user)
->get('users')
->assertResponseStatus(403);
}
This test will pass and confirm that a non admin user cannot access the url.
Since the Auth middleware redirects to a login route when unauthenticated by default you could also perform the following test:
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->assertRedirect('login');
}
Since at least Laravel 5.4, you'll want to use the assertStatus(403) method.
public function testNonAdminCannotManageUsers()
{
$user = Auth::loginUsingId(4);
$this->actingAs($user)
->visit('users')
->assertStatus(403);
}

Categories