I made my code where an administrator can send a message to a group, and soon all users within that group receive notification on the mobile app:
public function create(Request $request)
{
if(!($error = $this->isNotValidate($request))){
//Log::error(print_r("validado", true));
$message = Message::create($request->toArray());
$message->recives()->attach($request->recive_ids);
foreach($message->recives as $group){
foreach($group->users as $user){
$user->notify(new NotificationMessage($message));
}
}
$response = ['message' => $message];
return response($response, 200);
}
return response($error, 422);
}
I used the library: https://github.com/laravel-notification-channels/fcm it is working he send the notification to the mobile through the firebase.
my difficulty is that in the toFcm function I want to retrieve the message to build the notification I'm sending:
public function toFcm($notifiable)
{
return FcmMessage::create()
->setData(['message_id' => $this->invoice->id, 'message_created' => $this->invoice->created_at])
->setNotification(\NotificationChannels\Fcm\Resources\Notification::create()
->setTitle($this->invoice->title)
->setBody($this->invoice->content)
//->setImage('http://example.com/url-to-image-here.png')
)->setAndroid(
AndroidConfig::create()
->setFcmOptions(AndroidFcmOptions::create()->setAnalyticsLabel('analytics'))
->setNotification(AndroidNotification::create()->setColor('#0A0A0A'))
)->setApns(
ApnsConfig::create()
->setFcmOptions(ApnsFcmOptions::create()->setAnalyticsLabel('analytics_ios')));
}
I thought that in the variable $this->invoice or in the $notifiable would come the $message that I am passing as a parameter in the creation, but it does not pass, both are returning the user.
does anyone know how i can make this dynamic notification with my message data?
UPDATE
class NotificationMessage extends Notification
{
/**
* Specifies the user's FCM token
*
* #return string|array
*/
public function routeNotificationForFcm()
{
return $this->fcm_token;
}
public function via($notifiable)
{
return [FcmChannel::class];
}
public function toFcm($notifiable)
{
return FcmMessage::create()
->setData(['message_id' => $notifiable->id, 'message_created' => $notifiable->created_at])
->setNotification(\NotificationChannels\Fcm\Resources\Notification::create()
->setTitle($notifiable->title)
->setBody($notifiable->content)
//->setImage('http://example.com/url-to-image-here.png')
)->setAndroid(
AndroidConfig::create()
->setFcmOptions(AndroidFcmOptions::create()->setAnalyticsLabel('analytics'))
->setNotification(AndroidNotification::create()->setColor('#0A0A0A'))
)->setApns(
ApnsConfig::create()
->setFcmOptions(ApnsFcmOptions::create()->setAnalyticsLabel('analytics_ios')));
}
// optional method when using kreait/laravel-firebase:^3.0, this method can be omitted, defaults to the default project
public function fcmProject($notifiable, $message)
{
// $message is what is returned by `toFcm`
return 'app'; // name of the firebase project to use
}
}
I decided to invert the logic of who was my notify, now instead of the user being the notify, my message became
In my control I'm even simpler:
public function create(Request $request)
{
if(!($error = $this->isNotValidate($request))){
//Log::error(print_r("validado", true));
$message = Message::create($request->toArray());
$message->recives()->attach($request->recive_ids);
$message->notify(new NotificationMessage);
$response = ['message' => $message];
return response($response, 200);
}
return response($error, 422);
}
in my message template I made the following changes:
use Illuminate\Notifications\Notifiable;
...
class Message extends BaseModel
{
use Notifiable;
...
public function routeNotificationForFcm()
{
$tokens = [];
foreach($this->recives as $group){
foreach($group->users as $user){
$tokens = array_merge($tokens, $user->notifications()->pluck('token')->toArray());
}
}
return $tokens;
}
}
with that in my variable $notifiable started to receive the information of the message and then it was easy to pass them as parameter.
Related
i want to send notification to my clinic owner, when a clinic is added by admin. The following is my code,but mails are not sending,please not that email field in my db is clinicemail . Following is my code in clinic controller
public function storeClinics(Request $request)
{
$postdata = $request->all();
$api_key = Str::random(16);
$checkApiKey = Clinic::where('api_key', $api_key)->first();
if(!empty($checkApiKey)) {
$api_key = Str::random(16);
}
$clinic = new Clinic;
$clinic->clinicName=$postdata['user_name'];
$clinic->clinicFname=$postdata['contact_fname'];
$clinic->clinicLname=$postdata['contact_sname'];
$clinic->clinicAddress=$postdata['contact_address'];
$clinic->clinicCity=$postdata['contact_city'];
$clinic->clinicState=$postdata['contact_state'];
$clinic->clinicZip=$postdata['zip'];
$clinic->clinicEmail=$postdata['email'];
$clinic->clinicPhone=$postdata['phone'];
$clinic->clinicURL=$postdata['clinic_website'];
$clinic->clinicPub="no";
$clinic->api_key=$api_key;
$clinic->save();
Notification::route('mail', $clinic->clinicEmail)->notify(new ClinicRegisteredNotification($clinic));
return redirect('clinics');
}
I have also created a notification named ClinicRegisteredNotification in notificcations folder and following is code
<?php
namespace App\Notifications;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class ClinicRegisteredNotification extends Notification {
public function __construct($clinic) {
$this->user = $clinic;
}
public function via($notifiable) {
return ['mail'];
}
public function toMail($notifiable) {
return (new MailMessage)
->success()
->subject('Welcome')
->line('Dear ' . $this->clinic->clinicName . ', we are happy to see you here.')
->line('Please tell your friends about us.');
}
}
In the ClinicRegisteredNotification, try to add a protected attribute before the __construct($clinic) method and change the line in the constructor.
The beginning of ClinicRegisteredNotification should be this:
class ClinicRegisteredNotification extends Notification {
protected $clinic;
public function __construct($clinic) {
$this->clinic = $clinic;
}
This should solve the issue.
I have customer data in my database with their emails. In my case, i want to get user email from customer table and send a custom email to customer. I'm new to laravel and this is the very first time i'm working with laravel notification. Help me to do this!
I have created this SendMailController:
public function sendNotifications(Request $request, $id)
{
$id = $request->id;
$customer_id = DB::table('jobs')->select('customers_id')->where('id', '=', $id)->get();
$customer_email = DB::table('customer')->select('email')->where('id', '=', $customer_id)->get();
$customer_firstname = DB::table('customer')->select('firstname')->where('id', '=', $customer_id)->get();
sendEmail($customer_firstname, $customer_email);
return view('admin.sendNotifications');
}
I have created a sendEmail Notification class:
class sendEmail extends Notification
{
use Queueable;
public function __construct($customer_firstname, $customer_email)
{
$this->customer_email = $customer_email;
$this->customer_firstname = $customer_firstname;
}
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
return (new MailMessage)
->error()
->subject('Thank you!')
->from('hashankannangara#gmail.com', 'Sender')
->to($this->customer_email)
->line($this->customer_firstname.''.'Thanks for got services from us!');
}
public function toArray($notifiable)
{
return [
//
];
}
}
How can i pass the customer email to to() function? I want to display customer first name in email with Thanking them. How can i use a custom template and add to this email? I appreciate if you can help me.
https://laravel.com/docs/6.x/notifications#mail-notifications
You can use something like this in toMail method:
return (new CustomMail($this->customer))->to($this->customer->email);
and when you call notify you must pass a customer
use Mail;
$data = 'set data variable pass in view'
$email= 'receiver' email'
Mail::send('here set your file for view (ex. email.access(blade))', $data, function ($message) use ($email) {
$message->from('sender mail','Title')->subject('Register');
$message->to($email);
});
I am writing tests to validate that a locale is set for a notification and asserting that the correct translation is used in the notification's content. I have been unable to get the locale set on notifications when using Twilio: https://github.com/laravel-notification-channels/twilio
I have a notification test for a mail channel that uses a Mailable which is working as expected:
public function test_mail_notifications_use_localisation()
{
$user = factory(User::class)->create();
$user->notify(
(new WelcomeMailNotificationStub)
->locale('fr')
);
$this->assertContains('Bonjour Le Monde',
app('swift.transport')->messages()[0]->getBody()
);
}
class WelcomeMailStub extends \Illuminate\Mail\Mailable
{
public function build()
{
return $this->view('welcome-notification');
}
}
class WelcomeMailNotificationStub extends \Illuminate\Notifications\Notification
{
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
return (new WelcomeMailStub);
}
}
I would like to write a similar test for SMS notifications sent via Twilio but in my attempts so far the locale appears to be ignored when sending the notification and the default locale is instead used. Here's what I've come up with:
public function test_sms_notifications_use_localisation()
{
Notification::fake();
$user = factory(User::class)->create();
$user->notify(
(new WelcomeSmsNotificationStub)
->locale('fr')
);
Notification::assertSentTo(
$user,
WelcomeSmsNotificationStub::class,
function ($notification, $channels) use ($user)
{
return $notification->toTwilio($user)->content === 'Bonjour Le Monde'; // test fails here
}
);
}
class WelcomeSmsNotificationStub extends \Illuminate\Notifications\Notification
{
public function via($notifiable)
{
return [TwilioChannel::class];
}
public function toTwilio($notifiable)
{
return (new TwilioSmsMessage())
->content(__('welcome_notification.opening_text'));
}
}
If I dd() inside the callback in assertSentTo like this:
Notification::assertSentTo(
$user,
WelcomeSmsNotificationStub::class,
function ($notification, $channels) use ($user)
{
dd(
$notification,
$notification->toTwilio($user)
);
return $notification->toTwilio($user)->content === 'Bonjour Le Monde'; // test fails here
}
);
I get the following:
Tests\Unit\Notifications\WelcomeSmsNotificationStub {#116
+id: "ae164ce6-fa47-4730-b401-e6cc15b27e16"
+locale: "fr"
}
NotificationChannels\Twilio\TwilioSmsMessage {#2414
+alphaNumSender: null
+applicationSid: null
+maxPrice: null
+provideFeedback: null
+validityPeriod: null
+content: "Default welcome" <== using the default welcome instead of 'fr'
+from: null
+statusCallback: null
+statusCallbackMethod: null
}
Any advice on getting this working would be appreciated, thanks!
User exohjosh has solved the issue. I need to explicitly set the translated string's locale in the SMS Notification's toTwilio method like this:
__('welcome_notification.opening_text', [], $this->locale)
whereas when using Laravel's Mailable this was done automatically.
Edit
Event better solution if you're using views is to use Illuminate\Support\Traits\Localizable then you can do this:
public function toTwilio($notifiable)
{
return $this->withLocale($this->locale, function() {
$content = View::make('welcome-notification')->render();
return (new TwilioSmsMessage())->content($content);
});
}
I am building a test API. I have created a Controller Page which extends from yii\rest\Controller. Actions needs to send a response.
To access actions in this controller, a service_id value needs to be posted. If present I need to evaluate if that service_id exists, if it is active and belongs to the user logged in. If validation fails, I need to send a response.
I am trying to do it using beforeAction(), but the problem is that return data is used to validate if action should continue or not.
So my temporary solution is saving service object in a Class attribute to evaluate it in the action and return response.
class PageController extends Controller
{
public $service;
public function beforeAction($action)
{
parent::beforeAction($action);
if (Yii::$app->request->isPost) {
$data = Yii::$app->request->post();
$userAccess = new UserAccess();
$userAccess->load($data);
$service = $userAccess->getService();
$this->service = $service;
}
return true;
}
public function actionConnect()
{
$response = null;
if (empty($this->service)) {
$response['code'] = 'ERROR';
$response['message'] = 'Service does not exist';
return $response;
}
}
}
But I can potentially have 20 actions which require this validation, is there a way to return the response from the beforeAction method to avoid repeating code?
You can setup response in beforeAction() and return false to avoid action call:
public function beforeAction($action) {
if (Yii::$app->request->isPost) {
$userAccess = new UserAccess();
$userAccess->load(Yii::$app->request->post());
$this->service = $userAccess->getService();
if (empty($this->service)) {
$this->asJson([
'code' => 'ERROR',
'message' => 'Service does not exist',
]);
return false;
}
}
return parent::beforeAction($action);
}
maybe paste in beforeAction after $this->service = $service;
if (empty($this->service)) {
echo json_encode(['code' => 'ERROR', 'message' => 'Service does not exist']);
exit;
}
I now create function for get all current user messages from messages table. And in general can I change current array value using another function. For example here I must get sended date in needed format. Also get email from users table using sender id.
Current function code
public function user_messages()
{
$user_id = Auth::user()->id;
$messages = Message::where('to', $user_id)->get();
foreach ($messages as $message)
{
echo $message->subject; // Example Subject
echo $message->message; // Long message text
echo $message->from; // Sender id. For example: 2
echo $message->created_at; // Sended date
}
//return $messages;
}
And can I call this function on another Controller which return needed view?
Updates question
Now I write another my function to get email. This method good or not?
public function getEmail($id)
{
return User::where('id', $id)->first()->email;
}
foreach ($messages as $message)
{
echo $this->getEmail($message->from)."<br>";
}
You can use eloquent relationship in messages Model add sender and receiver function
public function sender() {
return $this->belongsTo(User::class, 'from');
}
public function receiver() {
return $this->belongsTo(User::class, 'to');
}
and format the date as you wish with mutation:
public function getCreatedAT($value) {
return $this->attributes['created_at']->toIso8601String();
}
Then you can access the $message->sender and $message->receiver to get there email;
If I understand your question than I think best way for you it's using scope, and relations:
Message model:
/**
* Sender relation
*
* #return User
*/
public function sender() {
return $this->belongsTo(User::class, 'from');
}
/**
* Receiver relation
*
* #return User
*/
public function receiver() {
return $this->belongsTo(User::class, 'to');
}
/**
* scope that return only messages which send specific user
* #return \Illuminate\Database\Eloquent\Builder
*/
public function scopeSentToUser($query, $user_id == null)
{
if (!$user_id && !\Auth::check()) {
throw new \InvalidArgumentException('User ID is undefined');
} else {
$user_id = \Auth::id();
}
return $query->whereHas('receiver', function($sql) use ($user_id) {
$sql->where('id', $user_id);
});
}
Any Controller:
/** #var \Illuminate\Database\Eloquent\Collection $messages Messages which were sent to auth user **/
$messages = Message::sentToUser()->get();
/** #var \Illuminate\Database\Eloquent\Collection $messages Messages which were sent to user 2 **/
$anotherUserMessages = Message::sentToUser(2)->get();
foreach ($messages as $message)
{
echo $message->subject; // Example Subject
echo $message->message; // Long message text
echo $message->from; // Sender id. For example: 2
echo $message->created_at; // Sent date
var_dump($message->sender); // Sender user model
var_dump($message->receiver); // Receiver user model
}