Laravel : send email to other_emails - php

I'm trying to send an email to other_emails, so that when the user 1 already book for his friends, the user 1 got email and his friends also got an email, i tried to use foreach for sending the email the other_emails but i got this error message Undefined variable: isi_email1
How can i fix it?
The Controller :
$isi_email1 = [
'title'=>'Thank you for your purchase',
'body'=>'Please give us your review about your experience using Pintunuswantara Travel. Link : https://pintunuswantara.com/review'
];
$subject = [$booking->email];
Mail::to($subject)->send(new OthersEmail($isi_email1));
$others = Booking::select('other_emails');
foreach($others as $other){
Mail::to($other)->send(new OthersEmail($isi_email1));
}
The OthersEmail :
public $isi_email1;
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct()
{
//
$this->isi_email1 = $isi_email1;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from('admin#pinnuss.com')
->subject('Thank you')
->view('other_email');
}

The problem seems to be the variable scope/context. In order for you to access a variable in a function within a class, you must pass it in as a parameter; it doesn't inherit the context of where its called.
IE: in this example, your OthersEmail::construct function must accept the $isi_email1 parameter in order to then assign it to its property.
Change the constructor function to look like this in order to then assign and be able to pass through the variable:
public function __construct(array $isi_email1) {
$this->isi_email1 = $isi_email1;
}
If you don't intend on using typed parameters, you can remove the array from the parameter definition.
public function __construct($isi_email1) {
// etc.
}
Your controller class is already trying to pass the variable in, so there shouldn't have to be any changes there in order for this to work.

Related

send mail returns null

When trying to send a message, In my view verifyEmail.blade.php $agent is null and $agent->name says trying to get property of non object.
verifyEmail.blade.php
<body>
<h2> Welcome to our website{{ $agent->name }} </h2>
click here to verify your email
</body>
This is how I am using the Mail class. In my Mail folder in verifyEmail file I have a construct function which collects the $agent model.
verifyEmail.php
class verifyEmail extends Mailable
{
public $agent;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($agent)
{
$this->$agent = $agent;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('emails.verifyEmail');
}
}
And in my admin controller which does the registration for the user looks like this. The send method passes the agent model to the verifyEmail.php which was working in the tutorial I watched. How can I make agent model available in verifyEmail.blade.php
AdminController
$agent = new agent($data);
$agent->name = $data["name"];
$agent->email = $data["email"];
$agent->nrc = $data["nrc"];
$agent->resident = $data["residents"];
$agent->password = Hash::make($data["password"]);
$agent->save();
verifyUser::create(
[
'token' => Str::random(60),
'agent_id' => $agent->id,
]
);
Mail::to($agent->email)->send(new verifyEmail($agent));
I think there can be a slight modification in the code provided to solve this.
Inside the file verifyEmail.php, the line
$this->$agent = $agent;
should be
$this->agent = $agent;
Because $this->$agent might not be able to find the class level variable 'agent' and update its value that is provided in the constructor so it will have the default value null which is shown afterwards.
Configuring The Sender
Using The from Method
First, let's explore configuring the sender of the email. Or, in other words, who the email is going to be "from". There are two ways to configure the sender. First, you may use the from method within your mailable class' build method:
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->from('example#example.com')
->view('emails.orders.shipped');
}
Using A Global from Address
However, if your application uses the same "from" address for all of its emails, it can become cumbersome to call the from method in each mailable class you generate. Instead, you may specify a global "from" address in your config/mail.phpconfiguration file. This address will be used if no other"from" address is specified within the mailable class:
'from' => ['address' => 'example#example.com', 'name' => 'App Name'],
In addition, you may define a global "reply_to" address within your config/mail.php configuration file:
'reply_to' => ['address' => 'example#example.com', 'name' => 'App Name'],
So you can try this In verifyEmail.php Change this
public function build()
{
return $this->view('emails.verifyEmail');
}
To this
public function build()
{
return $this->from('info#domain.com')->view('emails.verifyEmail');
}

Laravel Controller Type Hinting

After creating a model with -mcr (php artisan make:model Institution -mrc), the show function in controller was scaffolded as:
/**
* Display the specified resource.
*
* #param \App\Organization\Institution $institution
* #return \Illuminate\Http\Response
*/
public function show(Institution $institution)
{
return view('institutions.show', ['institution' => $institution]);
}
The return view... was inserted by me. I was expecting it to have it populated with the object whose id was sent in the parameters.
/institutions/1
But, after using dd($institution), I verified that it has the ID, not the object.
Shouldn't this variable return me the object?
This is called Route Model Binding. Your route will need to look something like:
Route::get('institutions/{institution}', 'InstitutionController#show');
and then as per your controller
public function show(Institution $institution)
{
return view('institutions.show', compact($institution))
}
You can read more on this here.
I imagine your route had the parameter called {id} rather than {institution}.
Replace the parameter of show function
public function show(Institution $institution)
{
return view('institutions.show', compact($institution))
}
becomes
public function show($id)
{
$institution = App\Institution::findOrFail($id);;
return view('institutions.show', compact('institution'));
}
and in your routes
Route::get('institutions/{id}', 'InstitutionController#show');

Laravel PHP Traits with models

I have a PHP trait that I will use in any model that can do a certain set of actions. For example one of these actions is completion where completed_at is marked with a timestamp.
The trait method is:
/**
* #return $this
* #throws Exception
*/
public function markCompleted(){
if($this->canDoAction('complete')){
$this->completed_at = Carbon::now();
return $this;
}
}
In my controller I am calling this on a model that can do this action like below.
$app->markCompleted()->save();
The $app when I view its contents it is not null.
Running this command returns an error like
local.ERROR: Call to a member function save() on null
Wouldn't $this represent the model that uses this trait?
Another variation on what The Alpha said.
/**
* #return $this
* #throws Exception
*/
public function markCompleted(){
if($this->canDoAction('complete')){
$this->completed_at = Carbon::now();
}
return $this;
}
This way you always return a model, and you can chain other functions before the save is performed if you needed.
If the condition doesn't meet then null will be returned, so instead of calling the save separately, do that inside that method, for example:
public function markCompleted()
{
if ($this->canDoAction('complete')) {
$this->completed_at = Carbon::now();
return $this->save(); // true/false
}
}
Then use it like:
$app->markCompleted();
The way way, you coded, the save method will be called even if the condition doesn't match and that's a side effect.

Check if Backend User belongs to Group with OctoberCMS Laravel?

I'm using OctoberCMS based on Laravel.
I have a backend user, Matt in Groups owners, administrators.
How do I check if user belongs to a specific group to allow authentication?
I was told I need to pass a Group Object, but I don't know what that is.
use Auth;
use BackendAuth;
use Backend\Models\User;
if (BackendAuth::check()) {
// get current backend user
$backend_user = BackendAuth::getUser();
// get current backend user's groups
$backend_user_groups = Backend::getUser()->groups;
// authenticate
if ($backend_user->inGroup('administrators') {
}
}
Error
public function inGroup($group)
Call to a member function getKey() on string
Another way I've tried
if (User::inGroup('administrators') {
}
Error
Non-static method October\Rain\Auth\Models\User::inGroup() should not be called statically
Docs
https://octobercms.com/docs/backend/users
https://github.com/octobercms/library/blob/master/src/Auth/Models/User.php
There could be some helper functions for this but you can also use this:
$backend_user->groups()->whereName('administrators')->exists();
You can also extend the backend user model and add a helper method to it to check roles. Do the following in the boot() method of your plugin:
use Backend\Models\User as BackendUser;
public function boot()
{
BackendUser::extend(function($model) {
$model->addDynamicMethod('hasRole', function($role) use ($model) {
return $model->groups()->whereName($role)->exists();
});
$model->addDynamicMethod('isAdmin', function() use ($model) {
return $model->hasRole('administrators');
});
}
}
I think first you should try to understand the errors before doing the permissions part
public function inGroup($group)
Call to a member function getKey() on string
Did you look what does the inGroup() function do ? This method does not expect a string as a parameter
Here's the complete function :
/**
* See if the user is in the given group.
* #param Group $group
* #return bool
*/
public function inGroup($group)
{
foreach ($this->getGroups() as $_group) {
if ($_group->getKey() == $group->getKey()) <<== Call to a member function getKey() on string
{
return true;
}
}
return false;
}
As regards the second error
Non-static method October\Rain\Auth\Models\User::inGroup() should not be called statically
You should initialize non-static methods like this :
(new User)->someMethod()

Laravel ioc automatic resolution - works from controller but not from custom class

Namespaces omitted for brevity...
I have written the following service provider and registered in config/app.php:
class OfferServiceProvider extends ServiceProvider
{
public function register()
{
$this->registerLossControlManager();
}
protected function registerLossControlManager()
{
$this->app->bind('LossControlInterface', 'LossControl');
}
}
Here is my LossControlInterface
interface LossControlInterface
{
/**
* #param int $demandId
* #param float $offerTotal
* #param float $productTotal
* #param null|int $partnerId
* #return mixed
*/
public function make($demandId, $offerTotal, $productTotal, $partnerId = null);
/**
* #return float
*/
public function getAcceptableLoss();
/**
* #return bool
*/
public function isAcceptable();
/**
* #return bool
*/
public function isUnacceptable();
/**
* #return null
*/
public function reject();
}
Now within the controller, I can inject the LossController as follows:
use LossControlInterface as LossControl;
class HomeController extends BaseController {
public function __construct(LossControl $lossControl)
{
$this->lossControl = $lossControl;
}
public function getLossThresholds()
{
$lossControl = $this->lossControl->make(985, 1000, null);
var_dump('Acceptable Loss: ' . $lossControl->getAcceptableLoss());
var_dump('Actual Loss: ' . $lossControl->calculateLoss());
var_dump('Acceptable? ' . $lossControl->isAcceptable());
}
}
However if I try to dependency inject the LossControlInterface from within a custom class called by a command:
[2014-09-02 13:09:52] development.ERROR: exception 'ErrorException' with message 'Argument 11 passed to Offer::__construct() must be an instance of LossControlInterface, none given, called in /home/vagrant/Code/.../ProcessOffer.php on line 44 and defined' in /home/vagrant/Code/.../Offer.php:79
It appears as though I am unable to dependency inject the interface into a custom class, but I can when dependency injecting into a controller.
Any thoughts on what Im doing wrong or have omitted to get the automatic resolution working?
The IoC is automatic within controllers, and you don't see the injection because Laravel handles the construction of controllers for you. When creating any other custom class by using the new keyword, you will still need to send in all of the parameters needed to it's constructor:
$myClass = new ClassWithDependency( app()->make('Dependency') );
You can hide this, to a degree, by funneling creation of your custom class through a service provider:
// Your service provider
public function register()
{
$this->app->bind('ClassWithDependency', function($app) {
return new ClassWithDependency( $app->make('Dependency') );
});
}
Then just have the IoC make it whenever you need it:
$myClass = app()->make('ClassWithDepenency');
In your case, you can change your code to look like this:
private function setOffer(Offer $offer = null) {
$this->processOffer = $offer ?:
new Offer( app()->make('LossControlInterface') );
}
A perhaps cleaner approach could be to create a service provider and an OfferFactory which gets injected into your controller. The controller can then request the factory to create the offer whenever it needs one:
// Controller
public function __construct(OfferFactory $offerFactory)
{
$this->offerFactory = $offerFactory;
}
public function setOffer(Offer $offer = null)
{
$this->processOffer = $offer ?: $this->offerFactory->createOffer();
}
// OfferFactory
class OfferFactory
{
public function createOffer()
{
return app()->make('Offer');
}
}
This has the benefit of completely decoupling your controller from the logic behind the creation of the offer, yet allowing you to have a spot to add any amount of complexity necessary to the process of creating offers.
In Laravel 5.2 the simplest solution for your particular problem would be to replace
new Offer();
with
App::make('Offer');
or even shorter
app('Offer');
which will use Laravel Container to take care of dependencies.
If however you want to pass additional parameters to the Offer constructor it is necessary to bind it in your service provider
App::bind('Offer', function($app, $args) {
return new Offer($app->make('LossControl'), $args);
});
And voila, now you can write
app('Offer', [123, 456]);
In laravel 5.4 (https://github.com/laravel/framework/pull/18271) you need to use the new makeWith method of the IoC container.
App::makeWith( 'App\MyNameSpace\MyClass', [ $id ] );
if you still use 5.3 or below, the above answers will work.

Categories