Pass data between different "Via" Laravel Notification - laravel

Do you know how to pass data between 2 different "Via" notification?
This is the situation:
I have created 2 custom channels for notification
PushNotificationChannel
CustomDatabase
In my Notification Class I have this:
class GeneralNotification extends Notification
{
use Queueable;
private $notificationType;
private $sender;
public function __construct($notificationType, $sender)
{
$this->notificationType = $notificationType;
$this->sender = $sender;
}
public function via($notifiable)
{
return [CustomDatabaseChannel::class, PushNotificationChannel::class];
}
public function toPushNotification($notifiable)
{
return [
//
];
}
public function toCustomDatabase($notifiable)
{
return [
//
];
}
}
So this will first execute the toCustomDatabase method, and then the toPushNotification method.
What I want is after I save the data into de database, pass it (the inserted record) to the toPushNotification method.
I was testing with assigning for example:
public function toCustomDatabase($notifiable)
{
$this->notificationType = 'test';
return [
//
];
}
but when I do:
public function toPushNotification($notifiable)
{
dd($this->notificationType);
return [
//
];
}
It shows me the original notificationType, and not the value I changed in the toCustomDatabase method.

What I did was to add the inserted record into de session() (Although in API Middleware the session is not persistent, it works within the request cycle). Then in the toPushNoification method I retreive that session.

Related

Laravel - Instantiate object and keep it within all controller's methods

I'm working with this case where I need to instantiate an object after a form is submitted in a controller. Everything's working fine until I call this object (as a property) from another method. It appears to be null.
If I intentiate the object from constructor method, I have no problem at all.
I can't keep this object in session because of closure.
Here's what i got so far.
// Version with the object iniate within the constructor that's working
class SearchConsoleController extends Controller
{
private $console;
protected function __construct() {
$callback = route('searchconsole.callback') ;
$this->console = $this->setConsole(env('CLIENT_ID'), env('CLIENT_SECRET'), $callback);
}
private function setConsole($cliendId, $cliendSecret, $callback){
$console = new Console(new Google_Client(), $cliendId, $cliendSecret, $callback);
return $console;
}
public function index(Request $request) {
return view('searchconsole.index')->with('authUrl', $this->console->getAuthUrl());
}
public function callback(Request $request){
if ($request->has('code')) {
$this->console->acceptCode($request->get('code'));
return redirect()->action('SearchConsoleController#listSites', [$request]);
}
else{
die('error');
}
}
Now the version which i'm stucked wih
class SearchConsoleController extends Controller
{
private $console;
private $callback;
protected function __construct() {
$this->callback = route('searchconsole.callback') ;
}
private function setConsole($cliendId, $cliendSecret, $callback){
$console = new Console(new Google_Client(), $cliendId, $cliendSecret, $this->callback);
return $console;
}
public function index(Request $request) {
// VIEW WITH A FORM FROM WHICH I GET CLIENT_SECRET & CLIENT_ID var
return view('searchconsole.index');
}
public function getAuthUrl(Request $request) {
// FORM FROM INDEX IS SUBMITTED
$clientId = ($request->has('google-client-id')) ?
$request->get('google-client-id') :
null
;
$clientSecret = ($request->has('google-client-secret')) ?
$request->get('google-client-secret') :
null
;
$this->console = $this->setConsole($clientId, $clientSecret, $this->callback);
return $this->console->getAuthUrl();
}
public function callback(Request $request){
if ($request->has('code')) {
// ***** MY PROBLEM *********
$this->console->acceptCode($request->get('code')); // HERE $this->console IS NULL;
// *******************
return redirect()->action('SearchConsoleController#listSites', [$request]);
}
else{
die('error');
}
}
I just can't figure out how I can do this so console is still available
UPDATE :
following #iamab.in advice, i looked into Service Provider but i just dont know how i can instante the Console Object within the service provider.
Here's what i've done.
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Helpers\Console;
use Google_Client;
use Illuminate\Support\Facades\Route;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(Console::class, function() {
$request = app(\Illuminate\Http\Request::class);
$clientId = ($request->has('google-client-id')) ?
$request->get('google-client-id') :
null
;
$clientSecret = ($request->has('google-client-secret')) ?
$request->get('google-client-secret') :
null
;
$callback = Route::get()->name('searchconsole.callback');
return new Console(new Google_Client(), $clientId, $clientSecret, $callback);
});
}
public function boot(){}
....
I just dont know how and where to implement it.
Thanks again
Update#2 :
okay my solution was working, I just didnt launch the correct app ..... 😅

How to auto populate Laravel Nova Action Fields with their respective values from database?

This is the code I have inside my Action Class:
public function fields()
{
return [
Date::make('checkin_date'),
Date::make('checkout_date'),
Textarea::make('remark'),
Text::make('holder_name'),
Text::make('holder_surname'),
Text::make('clientReference'),
];
}
What I'm looking for is to show the actual database value on each field. So a user would either choose to edit or keep values as they are.
You can access the request object on the action definition and use a constructor to pass the value to the action.
class MyDemoAction extends Action
{
use InteractsWithQueue, Queueable;
public function __construct(MyDemoModel $model) {
$this->model = $model;
}
public function handle(ActionFields $fields, Collection $models)
{
//
}
public function fields()
{
return [
Date::make('checkin_date')->default(function() {
$this->model->my_value;
}),
Date::make('checkout_date'),
Textarea::make('remark'),
Text::make('holder_name'),
Text::make('holder_surname'),
Text::make('clientReference'),
];
}
To make sure that you can always pass a valid MyModel object, you can limit your action to only be visible on resourceDetail.
Registering A

Laravel Notification asserting the data passed down to mail markdown view

I am working on a Laravel project. I am writing integration/ feature tests for my application. I am now writing a test where I need to assert the data passed to the email notification and the data passed to its view. I found this link to do it, https://medium.com/#vivekdhumal/how-to-test-mail-notifications-in-laravel-345528917494.
This is my notification class
class NotifyAdminForHelpCenterCreated extends Notification
{
use Queueable;
private $helpCenter;
public function __construct(HelpCenter $helpCenter)
{
$this->helpCenter = $helpCenter;
}
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
return (new MailMessage())
->subject("Help Center registration")
->markdown('mail.admin.helpcenter.created-admin', [
'helpCenter' => $this->helpCenter,
'user' => $notifiable
]);
}
}
As you can see in the code, I am passing data to mail.admin.helpcenter.created-admin blade view.
This is my test method.
/** #test */
public function myTest()
{
$body = $this->requestBody();
$this->actingAsSuperAdmin()
->post(route('admin.help-center.store'), $body)
->assertRedirect();
$admin = User::where('email', $body['admin_email'])->first();
$helpCenter = HelpCenter::first();
Notification::assertSentTo(
$admin,
NotifyAdminForHelpCenterCreated::class,
function ($notification, $channels) use ($admin, $helpCenter) {
$mailData = $notification->toMail($admin)->toArray();
//here I can do some assertions with the $mailData
return true;
}
);
}
As you can see my comment in the test, I can do some assertions with the $mailData variable. But that does not include the data passed to the view. How can I assert or get the data or variables passed to the blade view/ template?
As you can see here, there is a viewData property on the MailMessage class which contains all the data passed to the view, no need to turn the notification into an array.
$notification->toMail($admin)->viewData
So it would be something like this in your case:
/** #test */
public function myTest()
{
$body = $this->requestBody();
$this->actingAsSuperAdmin()
->post(route('admin.help-center.store'), $body)
->assertRedirect();
$admin = User::where('email', $body['admin_email'])->first();
$helpCenter = HelpCenter::first();
Notification::assertSentTo(
$admin,
NotifyAdminForHelpCenterCreated::class,
function ($notification, $channels) use ($admin, $helpCenter) {
$viewData = $notification->toMail($admin)->viewData;
return $admin->is($viewData['user']) && $helpCenter->is($viewData['helpCenter']);
}
);
}

Laravel 5 Sanitizing Required Field Behavior

I am trying to sanitize the user input in my application following this article
Below is my request
class TestRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
$this->sanitize();
return [
'title'=>'required|max:100'
];
}
public function sanitize()
{
$input = $this->all();
if(!empty($input))
{
$input['title'] = trim(strip_tags($input['title']));
$this->replace($input);
}
}
}
Tough the title is required field, if I try to put <h1></h1> as input in the title field, as per the logic in sanitize() function the tags are stripped away, but an empty string is saved in the database. The required field validation in the rules in not taking any effect.
How to handle this?
Update:
Below is the controller method for saving the request.
public function save(TestRequest $request)
{
$input = $request->all();
...
}
First option is to use merge() instead of replace() in your code, i.e.:
$this->merge( ['title' => trim(strip_tags($input['title']))] );
Second option is to override the all() function, i.e.:
public function all()
{
$input = parent::all();
if( !empty($input) )
{
$input['title'] = trim(strip_tags($input['title']));
}
return $input;
}
In the last code example you dont have to use the sanitize() function.

Laravel one-to-many save Carbon error

I have a class called SubjectData:
class SubjectData extends Model
{
protected $table = 'subject_datas';
protected $fillable = ['firstname','lastname','birthdate','birthcity','months'];
protected $dates = ['birthdate'];
public function setBirthdateAttribute($date)
{
// So we can add the time, not just he php date
$this->attributes['birthdate'] = Carbon::createFromFormat('d/m/Y', $date);
}
public function anamnesis() {
return $this->belongsTo('App\Anamnesis');
}
}
And I have a class called Anamnesis:
class Anamnesis extends Model
{
public function meetingTest() {
return $this->belongsTo('App\MeetingTest');
}
public function subject() {
return $this->belongsTo('App\Subject','subject_id','id');
}
public function subjectData() {
return $this->hasOne('App\SubjectData');
}
public function scholarHistory() {
return $this->hasOne('App\ScholarHistory');
}
public function familyHistory() {
return $this->hasOne('App\FamilyHistory');
}
public function psicodiagnosis() {
return $this->hasOne('App\Psicodiagnosis');
}
}
The store function of the SubjectController class works like this:
public function store(CreateSubjectRequest $request)
{
$input = $request->all();
// Let's generate the anamnesis of the subject
$anamnesis = Anamnesis::create();
$anamnesis->save();
$newSubjectData = $this->saveSubjectData($input);
$anamnesis->subjectData()->save($newSubjectData);
......
......
}
where the function called is:
public function saveSubjectData($input)
{
$subjectData['firstname'] = $input['firstname'];
$subjectData['lastname'] = $input['lastname'];
$subjectData['birthcity'] = $input['birthcity'];
$subjectData['birthdate'] = $input['birthdate'];
return SubjectData::create($subjectData);
}
The problem is with the "birthdate" property.
If i check the value of $newSubjectData (dd($newSubjectdata)) after the call $this->saveSubjectData($input) the value of the birthdate is exactly the one i set on the calendar in the frontside (and also in the db the value is correct)
If I put the dd($anamnesis->subjectData) after the call $anamnesis->subjectData()->save($newSubjectData) the result is the "today" date and also in the DB the value is not the one I set but the date of today.
I can't find the error
P.S. The calendar is inside a Vue template
I think the problem is that, the date must be an instance of Carbon or is properly formatted according to your database table. Try the following inside your saveSubjectData() method
$subjectData['birthdate'] = Carbon\Carbon::parse($input['birthdate']
I write down the answer but i thank John Aldrin that guided me in the right direction.
You have to put the timestamp('birthdate') AFTER the default timestamps of the migration table (so at the end of the migration table)
I don't know why. If someone knows please explain !

Resources