How to send email in laravel? - laravel

I want to send the data of the last order just made by the user
I already have my .env configured
AfterOrder Class: (Class type mail)
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Models\Order;
class AfterOrder extends Mailable
{
use Queueable, SerializesModels;
public $order;
public function __construct(Order $order)
{
$this->Order = $order;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('mail.after-order');
}
}
View:
<div class="container">
<h1>Name: {{$order->user->name}}</h1>
</div>
the user table is a belongsto of orders
Controller:
public function sendMail(Order $order) {
$order = $order->newQuery();
$order->whereHas('user', function($query){
$query->where('email', '=', \Auth::user()->email);
});
$order->orderBy('id', 'desc')->first();
$user = User::where('email', '=', \Auth::user()->email)->first();
Mail::to($user->email)->send(new AfterOrder($order));
//return redirect()->route('home')->with(['message' => 'Thank you for shopping at Sneakers!']);
}
Whats wrong? i got this error

$order is still a Builder object when you do this.
$order->orderBy('id', 'desc')->first();
To get the actual Model, you need to do the following:
$order = $order->orderBy('id', 'desc')->first();

Related

Pass model to mail view

I have several methods that require email submissions. An example is, after making a purchase.
My class Mailable
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Models\Order;
class AfterOrder extends Mailable
{
use Queueable, SerializesModels;
public $order;
public function __construct(Order $order)
{
$this->Order = $order;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->subject('Thanks for your purchase')->view('mail.after-order');
}
}
My mail view
<div class="container">
<h1>Nombre: {{\Auth::user()->email}}</h1>
<h1>Order: {{$order->reference}}</h1>
</div>
My Controller
public function sendMail(Order $order) {
$order = $order->newQuery();
$order->whereHas('user', function($query){
$query->where('email', '=', \Auth::user()->email);
});
$order = $order->orderBy('id', 'desc')->first();
$user = User::where('email', '=', \Auth::user()->email)->first();
Mail::to($user->email)->send(new AfterOrder($order));
//return redirect()->route('home')->with(['message' => 'Thank you for shopping at Sneakers!']);
}
What am I doing wrong? If I, for example, in my controller make a $ order-> reference I get the order reference but when passing the variable to the view it treats me as null or empty
You should use the with method
public function build()
{
return $this->view('mail.after-order')
->with([
'orderName' => $this->order->name,
'orderPrice' => $this->order->price,
]);
}
in your mailable class AfterOrder. With that you have access to the name and the price of the order in your mail view.
You can then access these with {{ $orderPrice }} and {{ $orderName }} in your view.
Was a typo. just change $this->Order = $order; to $this->order = $order;

Laravel generates error while sending lists of posts to users

RegistrationController.php
use App\User;
use App\Post;
use App\Notifications\LatestPosts;
use App\Notifications\WelcomeEmail:
public function store()
{
auth()->login($user);
$allUsers = User::latest()->get();
$posts = Post::latest()->get();
$user->notify(new WelcomeEmail($user));
$allUsers->notify(new LatestPosts($posts));
return redirect(‘/dashboard’);
}
WelcomeEmail.php
use App\User;
class WelcomeEmail extends Notification
{
use Queueable:
public $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function toMail($notifiable)
{
$user = $this->user;
return (new MailMessage)
->subject(‘Thanks for registering’)
->markdown(‘emails.newusers.welcome’, compact(‘user’));
}
}
LatestPosts.php
use App\Post;
class LatestPosts extends Notification
{
use Queueable;
public $posts;
public function __construct(Post $posts)
{
$this->posts = $posts;
}
public function toMail($notifiable)
{
$posts = $this->posts;
return (new MailMessage)
->subject(‘Latest posts for you’)
->markdown(‘emails.posts.latestposts’, compact(‘posts’));
}
}
New users register successfully, welcome email is sent successfully but it gives me this error for sending latest posts to users.
Argument 1 passed to App\Notifications\LatestPosts::__construct() must be an instance of App\Post, instance of Illuminate\Database\Eloquent\Collection given
Basically, I want to send a list of posts to all users (I know it’s not efficient to send it while new users register but just want to see how it will work out even if I send it while new users register) Someone please help me out in this. What do I do? Thanks in advance.
In registration controller
use App\User;
use App\Post;
use App\Notifications\LatestPosts;
use App\Notifications\WelcomeEmail:
public function store()
{
auth()->login($user);
$allUsers = User::latest()->get();
$posts = Post::latest()->get();
$user->notify(new WelcomeEmail($user));
foreach($allUsers as $u){
$u->notify(new LatestPosts($posts));
}
return redirect(‘/dashboard’);
}
LatestPost
use App\Post;
use Illuminate\Database\Eloquent\Collection;
class LatestPosts extends Notification
{
use Queueable;
public $posts;
public function __construct(Collection $posts)
{
$this->posts = $posts;
}
public function toMail($notifiable)
{
$posts = $this->posts;
return (new MailMessage)
->subject(‘Latest posts for you’)
->markdown(‘emails.posts.latestposts’, compact(‘posts’));
}
}
You should change the signature of your constructor:
use App\Post;
use Illuminate\Database\Eloquent\Collection;
class LatestPosts extends Notification
{
use Queueable;
public $posts;
public function __construct(Collection $posts) // use `Collection`, not `Post`
{
$this->posts = $posts;
}
public function toMail($notifiable)
{
$posts = $this->posts;
return (new MailMessage)
->subject('Latest posts for you')
->markdown('emails.posts.latestposts', compact('posts'));
}
}

Laravel 5.7 sending notifications using Expo

I'm using Laravel 5.7 for my backend (I'm new to Laravel) and I'm trying to use Expo push notification extension for Laravel to send notifications to my users.
I followed the steps explained, but I get lost to where I'm suppose to place the class ExpoNotification extends Notification and how to call it.
What I expect to happen is that every time an orders status get changed a notification is send to the user.
What is happening is that I get an error saying the class can't be found.
OrderController
public function update_order(Request $request, $id)
{
//Get the Order and update the status
Order::where('id', '=', $id )->update($request->only(['status']));
//Get the order with ::find so I can use $order->
$order = Order::find($id);
//Get user belonging to this order
$user= User::where('id', '=', $order->user_id);
//Get response with orders only posted the same day and are payed
$orders = Order::where('store_id', '=', $order->store_id)
->where('day', '=', $order->day )
->where('week', '=', $order->week )
->where('year', '=', $order->year )
->where('payment_status', '=', $order->payment_status)->get();
//send expo notification so the user gets his update
new ExpoNotification($order);
//return only relevant orders to the store
return OrderResource::collection($orders);
}
ExpoNotification
<?
namespace App\Notifications\ExpoNotification;
use App\Order;
use App\User;
use NotificationChannels\ExpoPushNotifications\ExpoChannel;
use NotificationChannels\ExpoPushNotifications\ExpoMessage;
use Illuminate\Notifications\Notification;
class ExpoNotification extends Notification
{
public function via($notifiable)
{
return [ExpoChannel::class];
}
public function toExpoPush($notifiable)
{
return ExpoMessage::create()
->badge(1)
->enableSound()
->body("Your {$notifiable->service} account was approved!");
}
}
Error from postman
<!DOCTYPE html><!--
Symfony\Component\Debug\Exception\FatalThrowableError: Class 'App\Notifications\ExpoNotification' not found in file /Users/salmanmohamed/Documents/apps/rapiobackend/app/Http/Controllers/OrderController.php on line 182
Stack trace:
1. Symfony\Component\Debug\Exception\FatalThrowableError->() /Users/salmanmohamed/Documents/apps/rapiobackend/app/Http/Controllers/OrderController.php:182
Answer
Provided by Mohammed
<?php
namespace App\Notifications;
use App\Order;
use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use NotificationChannels\ExpoPushNotifications\ExpoChannel;
use NotificationChannels\ExpoPushNotifications\ExpoMessage;
class ExNotification extends Notification
{
use Queueable;
protected $order;
public function __construct($order){
$this->order=$order;
}
public function via($notifiable)
{
return [ExpoChannel::class];
}
public function toExpoPush($notifiable)
{
return ExpoMessage::create()
->badge(1)
->enableSound()
->body("Your {$notifiable->service} account was approved!");
}
public function toArray($notifiable)
{
return [
//
];
}
}
Your wrong is your implementation of your ExpoNotification class it's namespace is App\Expo and you are using App\Notifications\ExpoNotification

Get onlyTrashed() does not exist in query builder

I am trying to get trashed rows from table messages:
public function trash() {
return $this->onlyTrashed()
->where('user_id', '=', $this->_u)
->orWhere('receiver', '=', $this->_u)
->orderBy('deleted_at', 'desc')->get();
}
I get this error:
Method Illuminate\Database\Query\Builder::onlyTrashed does not exist.
I checked up Builder and SoftDeletes files for onlyTrashed method and it does not exist, how can I look up to trashed messages from message table?
The only way I think about is to create method that doesn't return messages where delete_at is not null and for trashed to return only those where it is not null. But I am still wondering why this doesn't work since it is in documentation at this url:
https://laravel.com/docs/5.6/eloquent#soft-deleting
MORE INFO
Yes it is inside model and yes I added use SoftDeletes:
use Illuminate\Database\Eloquent\SoftDeletes; - on top
use SoftDeletes; after opening the class
Let me paste entire model here:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
class Messages extends Model
{
use SoftDeletes;
protected $fillable = [
'user_id', 'subject', 'text', 'receiver'
];
public $_u;
protected $dates = ['deleted_at'];
public function __construct() {
$this->_u = auth()->user()->user_id; //or some id as string
}
public function trash() {
return $this->onlyTrashed()
->where('user_id', '=', $this->_u)
->orWhere('receiver', '=', $this->_u)
->orderBy('deleted_at', 'desc')->get();
}
public static function trashed() {
return self::onlyTrashed();
}
}
And controller has:
public function __construct() {
$this->middleware('auth');
}
public function index($field = 'trash') {
if ($field !== "new") {
$messages = (new Msg)->$field();
$user = auth()->user();
return view('pages.messages', compact('messages', 'user'));
}
return view('pages.messages.new', compact('messages', 'user'));
}
I tried calling static as well and I tried doing it from tinker and still keep getting:
onlyTrashed() doesn not exist
You have to call the parent constructor:
public function __construct() {
parent::__construct();
$this->_u = auth()->user()->user_id;
}
I think what you want is to define the trash method static:
public static function trash() {
return self::onlyTrashed()
->where('user_id', '=', $this->_u)
->orWhere('receiver', '=', $this->_u)
->orderBy('deleted_at', 'desc')->get();
}
Then call this function by:
$messages = Messages::trash();
This should work
# YourModelController.php
/**
* Show only trashed
*
* #return \Illuminate\Http\Response
*/
public function trashed()
{
...
$trashed = YourModel::onlyTrashed()->get();
...
}
I have researched a little further and I got this:
From https://laravel.com/api/5.6/Illuminate/Database/Eloquent.html
I should have
SoftDeletesTrait
but I have
SoftDeletes
. In softdeletestrait we have onlyTrashed method but in SoftDeletes we do not.
So I copied that method from this page:
https://github.com/laravel/framework/blob/7d9e7068c49f945385673014d4cba4de28accd5e/src/Illuminate/Database/Eloquent/SoftDeletingTrait.php#L119
And added it to SoftDeletes class, now it works like it should. I haven't find why it doesn't exist inside SoftDeletes class so if anyone find out let us know!

Laravel trait function not found

I have look all over stackoverflow and google and I cannot seem to solve my trait function not found. I have tried composer dump-autoload, my composer.json have the app directory connected and even checked my namespace and trait names. Here is my user controller.
<?php
namespace App\Http\Controllers;
use App\User;
use App\Traits\ControllerTrait;
use App\Http\Requests\UpdateUser;
use Illuminate\Http\Request;
use App\Http\Requests\IndexUser;
class UserController extends Controller
{
use ControllerTrait;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show multiple users.
*
* #return \Illuminate\Http\Response
*/
public function index(IndexUser $request)
{
$per_page = 50;
$order_by = 'id';
$sort_by = 'ASC';
if($request->has('per_page')) {
$per_page = $request->input('per_page');
}
if($request->has('order_by')) {
$order_by = $request->input('order_by');
}
if($request->has('sort_by')) {
$sort_by = $request->input('sort_by');
}
$users = User::when($request->has('select'), function ($query) use ($request) {
selectPrepare($query, $request->input('select'));
})->when($request->has('include'), function ($query) use ($request) {
if(!empty($request->input('include'))) {
$includedTables = explode(',', $request->input('include'));
$tables = array_map('trim', $includedTables);
return $query->with($tables);
}
return $query;
})->orderBy("{$order_by}", "{$sort_by}")
->paginate($per_page);
return response()->json($users);
}
}
}
Here is my Trait
<?php
namespace App\Traits;
trait ControllerTrait
{
/**
* Function: scopeSelectPrepare
public function selectPrepare($query, $select) {
if(!empty($select)) {
$selectedColumns = explode(',', $select);
$columns = array_map('trim', $selectedColumns);
return $query->select($columns);
}
return $query;
}
}
As you can see my name space for the Trait is App\Traits and call the use App\Traits\ControllerTrait in my controller then can the use ControllerTrait to get the functions from the trait. When I try to get the function to use in my query it says: Call to undefined function App\Http\Controllers\selectPrepare()
Is there something I am missing? I am new to the traits functionality of laravel but I thought I was following all of the examples and naming conventions. Can anyone see what I am doing wrong.
You need to use $this when accessing trait methods, just like you would for any other method:
$users = User::when($request->has('select'), function ($query) use ($request) {
$this->selectPrepare($query, $request->input('select'));

Resources