Laravel send email to address from database - laravel

In my index view I show all the users and there is a button that will change the user status to active and not active. The code looks like this:
#foreach($users as $user)
<tr>
<td>{{$user->name}}</td>
<td>{{$user->surname}}</td>
<td>{{$user->email}}</td>
<td>
#if($user->is_active == 0)
{!! Form::model($user, ['method' => 'PUT', 'action'=>['AdminUserController#activateuser', $user->id]]) !!}
{!! Form::submit('Activate', ['class'=>'btn btn-primary']) !!}
{!! Form::close() !!}
#else
{!! Form::model($user, ['method' => 'PUT', 'action'=>['AdminUserController#activateuser', $user->id]]) !!}
{!! Form::submit('De-Activate', ['class'=>'btn btn-danger']) !!}
{!! Form::close() !!}
#endif
</td>
<td>{{$user->cell}}</td>
<td><button class="btn btn-primary">View Property</button></td>
<td><button class="btn btn-danger">Delete</button></td>
</tr>
#endforeach
So when I click on activate/deactivate button I trigger my activateuser function of the controller. After activation, an email is sent.
The controller looks like this:
public function activateuser(Request $request, $id){
$user = User::findOrFail($id);
if($user->is_active == 0){
$user->update([$user->is_active = 1]);
Mail::send(new activateUser());
}
else{
$user->update([$user->is_active = 0]);
}
return redirect()->back();
}
At the moment the email is going to myself and my Mailabçe looks like this:
public function build()
{
return $this->view('emails.activateuser')->to('wosleybago#gmail.com');
}
What I want instead is to send the email to the email address from the user email in the database table.
How can I do that?
So, someho I should get the $user->email

I usually want my emails have all the information in itself, so I pass User instance or whatever instance that holds data required to compose the mail.
So the Mailable has __construct(..) like this:
/**
* #var \App\User
*/
public $user; // since this is a public property its going to be available in view of mailable as $user
__construct(App\User $user) {
$this->user = $user;
// further more I set the to(), this is what you are after
$this->to($user->email, $user->name);
// and subject
$this->subject('You are activated!');
}
...
And now all you need to do in the controller is the following:
Mail::send(new activateUser($user));
As mentioned above, $user is available in the mail-view so you can use it there as well:
Hi, {{ $user->name }},
...
Note: change the activateUser to ActivateUser to follow PSR-2
Class names MUST be declared in StudlyCaps.
I also use queued mails so I set the $timeout and $tries properties right on the Mailable class.

Sending email is described in Doc: https://laravel.com/docs/5.6/mail#sending-mail
Put this code inside activateUser() function
Mail::to($user)->send(new YourMailableName());
Do not forget to import Mail and YourMailableName using "use" keyword.
Or you can use user email instead object
Mail::to($user->email)->send(new YourMailableName());
And remove ->to('wosleybago#gmail.com') from your Mailable/

You should pass User Email in when creating new activateUser instance, like so
Mail::send(new activateUser($user->email));
And then use this attribute later.

Sending Email to particular a person is quite simple. My suggestion would be as follows:
Use Queue to send mail later as it will take some time to respond from controller to view.
In existing code you can get the email of the current user and send it using a helper to() that comes with mail functionality of laravel.
You can code it like this.
if($user->is_active == 0){
$user->update([$user->is_active = 1]);
Mail::to($user->email)->send(new MailableClassInstance);
}

Related

When rendering a model, how to use a blade template instead of json as default?

Is it possible to assign a blade template to a model?
Instead of doing this:
#php $contact = Contact::find(1); #endphp
#include('contact', ['contact' => $contact])
I'd like to just do:
#php $contact = Contact::find(1); #endphp
{{ $contact }}
But latter obviously just spits out the model in json.
It is possible with PHP's __toString() magic method: https://www.php.net/manual/en/language.oop5.magic.php#object.tostring
Let's make an example for default User.php model.
First, create a blade file for that model, lets create that as /resources/views/model/user.blade.php and a dummy component;
<h1>{{ $user->name }}</h1>
<p>{{ $user->created_at->diffForHumans() }}</p>
Now make this default __toString() for User model.
Add this to app/Models/User.php ;
/**
* #return string
*/
public function __toString(): string
{
return view('model.user', ['user' => $this])->render();
}
Now you can test it directly in your routes/web.php ;
Route::get('test', function () {
echo \App\Models\User::first();
});
Or try to echo it in any view as;
{!! $user !!}
You can't use {{ $user }} because you need that HTML tags, so you have to use it as {!! $user !!}

Why error messages doesn't Appear in Laravel views?

I want to pass custom validation messages to my view using a custom request when storing a role.
I have create a new Request called StoreRoleRequest
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
use Illuminate\Contracts\Validation\Validator;
class StoreRoleRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required'
];
}
protected function formatErrors(Validator $validator)
{
return $validator->errors()->all();
}
public function messages()
{
return [
'name.required' => 'the name of the Role is mandatory',
];
}
}
And then pass this custom Request to my store function in the RoleController like this:
public function store(StoreRoleRequest $request)
{
Role::create($request->all());
return redirect(route('role.index'));
}
I have a view that show the create role form where the validation seems to work properly but without showing me error even if i call them into the view like this:
{!! Former::open()->action(route('role.store')) !!}
#if (count($errors->all()))
<div class="alert alert-danger">
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</div>
#endif
{!! Former::text('name')->label('Groupe name') !!}
{!! Former::text('display_name')->label('Displayed name') !!}
{!! Former::text('description')->label('Description') !!}
{!! Former::actions( Button::primary('Save')->submit(),
Button::warning('Clear')->reset() ,
Button::danger('Close')->asLinkTo('#')->withAttributes(['data-dismiss' => 'modal'])
)!!}
{!! Former::close() !!}
Has anyone an idea why the errors doesn't appear into the view ? am I looping something inside the custom Request ?
EDIT
NB: Even in the login and the registration form the errors doesn't appear anymore.
In this case i have change my middlware that was pointed to web ['middleware' => ['web'] to this:
Route::group(['middleware' => []], function ()
{
// other routes
Route::resource('role', 'RoleController');
});
and all my errors displayed perfectly.
have you locate the root cause about this issue ?
After your question update it seems, you have newer version of Laravel application (don't confuse it with Laravel framework).
To verify this, open file app/Providers/RouteServiceProvider.php and verify method what's the content of map method. In case it launches mapWebRoutes it means that you have 5.2.27+ application which applies web group middleware automatically.
In case web middleware is applied automatically you shouldn't apply web middleware in your routes.php file because it will cause unexpected behaviour.
So you should either remove web middleware from your routes.php in case you have mapWebRoutes defined in your RouteServiceProvider class or you can modify your RouteServiceProvider class to not apply web group middleware automatically. It's up to you which solution you choose.
Just for quick reference:
RouteServiceProvider for Laravel application 5.2.24
RouteServiceProvider for Laravel application 5.2.27
Try to ask if errors exists by this way:
#if($errors->any())
// Your code
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
// More code
#endif
Also remove the formatErrors function from the request... You don't need it...
The function messages() is responsible for returning your custom messages...
Regards.

Redirect back to same page (with variables) on form submit in Laravel 5

On my page events.index, I first display a list of events for the logged on user.
On my index page I have a form with option/select to let the user select and display the events of another user. When he submits that form, I would like my index function (controller) to use the $user_id value (from the form) and display the events.index page again, but for events of that selected user.
I'm not sure what would be the best approach:
Set a session variable to keep the user_id value? Not sure how to do that with a form.
Submit the form with a get method (and get an ugly ?user_id=1 URL)
Change my index route to accept the post method (although I already have that post/events route taken (by Route::post('events', 'EventsController#store'))
Not sure what would be a clean way to do this:
My route for events/index:
Route::get('events', [
'as' => 'event.index',
'uses' => 'EventsController#index'
]);
Events Controller
public function index()
{
// How to get the $user_id value from form?
if (empty($user_id))
{
$user_id = \Auth::user()->id;
}
$events = Event::where('events.user_id','=','$user_id');
$users = User::all();
return view('events.index')->with(['events' => $events])->with(['users' => $users]);
}
View for index
{!! Form::open(['route' => 'events.index', 'method' => 'get']) !!}
<select id="user_id" name="user_id">
#foreach($users as $user)
<option value="{{$user->id}}">{{$user->name}}</option>
#endforeach
</select>
{!! Form::submit('Show events for this user') !!}
{!! Form::close() !!}
#foreach($events as $event)
...
#endforeach
You can get the user_id from a Request object, you just need to inject it in the index method:
public function index(Request $request)
{
$user_id = $request->get('user_id') ?: Auth::id();
$events = Event::where('events.user_id','=','$user_id')->get();
$users = User::all();
return view('events.index')->with(['events' => $events])->with(['users' => $users]);
}

Laravel Filtering data between dates

I'm beginner in Laravel and web development and I have a silly question, I'm building a system that lists the user financial transactions. In the homepage is listed all the transactions made by the user. I put two fields up there to make the date filter of the transactions, but I don't know how to proceed this filter in Laravel.
I'm using datepicker and it is working fine, I also know that the validation system allows me to use Laravel date: after and date: before, but I don't know how and in which method in the controller send these dates. Here's my dates form code:
{!! Form::open(['route' => 'transactions.index']) !!}
{!! Form::label('data_inicio', 'De: ') !!}
{!! Form::input('date', 'data_inicio', null, ['class' => 'datepicker', 'data-date-format' => 'dd/mm/yy']) !!}
{!! Form::label('data_fim', 'Até: ') !!}
{!! Form::input('date', 'data_fim', null, ['class' => 'datepicker', 'data-date-format' => 'dd/mm/yy']) !!}
{!! Form::submit('Enviar') !!}
{!! Form::close() !!}
The method in the controller which calls the view of the homepage is the index, here's the index code:
public function index()
{
$transactions = Auth::user()->transactions;
return view('transactions.index', ['transactions' => $transactions]);
}
Here is how I show the data in the view:
#foreach( $transactions as $transaction )
<tr>
<td>{!! date('d-m-Y', strtotime($transaction->created_at)) !!}</td>
<td>{!! $transaction->title !!}</td>
<td>{!! $transaction->amount !!}</td>
</tr>
#endforeach
I need to send these dates I got to this same method (index) when the Pesquisar button was clicked to be able to seek in the database only the transactions of the proposed date, the problem is I do not know do this.
I tried to send these dates as parameter request to the index method, modifying it like this:
public function index(Request $request)
I got a Column Not Found error when I click in the submit, but I'm not using this request in any query in the method.
I really think that it has a simple way to do it and I appreciate any help!!
Here's my model class:
class Transaction extends Model {
protected $table = 'transactions';
protected $guarded = [];
public function users()
{
return $this->belongsTo('App\User');
}
}
Try this to obtain the dates in your controller:
$data_inicio = Input::get('data_inicio');
$data_fim = Input::get('data_fim');
Then you can use the dates to query your Transaction relation (assuming this a one to many relationship and is configured propperly)
$transactions = Transaction::whereBetween('created_at',[$data_inicio, $data_fim])->where('user_id',Auth::id())->get();

Laravel 5 Relationship Not Working?

In my app I have few models: User and Profile. The User model is only for companies, my app is for companies only. When a user registers, they only fill in their name, email address and password. My Profile model has columns for company name, address etc. My profile form does not work; not saving to the database. Here is the setup:
Controller for the form:
public function update($company_name)
{
$user = User::whereCompanyName($company_name)->firstOrFail();
$user->fill(Input::all());
$user->save();
flash('You have successfully edited your profile');
return redirect('/');
}
User.php:
public function profile()
{
return $this->hasOne('Profile');
}
Profile.php:
protected $fillable = ['company_name', 'company_logo', 'company_founded'];
public function user()
{
return $this->belongsTo('App\User', 'user_id','ID');
}
The Form:
{!! Form::model($user, array('method' => 'PATCH', 'route' => array('profile.update', $user->company_name), 'files' => true)) !!}
{!! Form::hidden('user_id', Auth::user()->id) !!}
// more fields
<div class="form-group">
{!! Form::label('company_name', 'Company Name') !!}
{!! Form::text('company_name', null, ['class' => 'form-control']) !!}
</div>
{!! Form::submit('Update Profile', ['class' => 'btn btn-primary']) !!}
{!! Form::close() !!}
Have I set the relationship correct? Nothing is saving to the database.
You’re updating the user model and the user model only. You need to also set the attributes in the profile relation:
$user->update(Input::all());
$user->profile->update(Input::all());
Your controller action could also be tidied up a bit, by using route–model binding to inject your User model instance, and also use the service container to provide a Request instance too so you’re not using the Input façade:
public function update(User $user, Request $request)
{
$user->update($request->all());
$user->profile->update($request->all());
flash('You have successfully updated your profile.');
return redirect('/');
}
I want to comment but do not have enough reputation :( A few days ago I found a little problem with this approach:
$user->update(Input::all());
$user->profile->update(Input::all());
In this case the mutators in related model (profile in the example) like this are not invoked (may be a bug):
public function setLoremIpsumAttribute($attr)
{
# code
}
In controller I tried another approach and it worked:
$user->update($request->all());
$user->profile->fill($request->all()['profile'])->push();
In Laravel 5 when you want to chain with relation, you need for exemple (Post with comment related) use the method from your comment.
Post::find(id)->comment()->where(your where statement)
Docs from Laravel:
If you need to add further constraints to which comments are retrieved, you may call the comments method and continue chaining conditions:
$comments = Post::find(1)->comments()->where('title', '=', 'foo')->first();

Resources