【问题标题】:Changing Laravel password reset mail to queued将 Laravel 密码重置邮件更改为排队
【发布时间】:2020-11-13 21:02:36
【问题描述】:

我在 Laravel 中遇到了队列问题,因为我以前从未使用过它们。我在 toMailUsing 方法和专门的服务提供商的帮助下覆盖了默认的重置密码电子邮件:

class MailServiceProvider extends ServiceProvider
{
    public function boot()
    {
        ResetPassword::toMailUsing(function ($notifiable, $token) {
            $url = url(route('password.reset', ['token' => $token, 'email' => $notifiable->getEmailForPasswordReset()]));
            dispatch(new SendEmail($url, $notifiable));
        });
    }
}

这是我的SendEmail 工作类:

class SendEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $user;
    protected $url;

    public function __construct($url, $user)
    {
        $this->user = $user;
        $this->url = $url;
    }

    
    public function handle()
    {
        $email = new ResetPassword($this->url, $this->user);
        Mail::to($this->user->email)->send($email);
    }
}

还有邮件本身:

class ResetPassword extends Mailable
{
    use Queueable, SerializesModels;
    protected $url;
    protected $user;


    public function __construct($url, $user)
    {
        $this->url = $url;
        $this->user = $user;
    }


    public function build()
    {
        return $this->markdown('emails.password_reset', ['url' => $this->url, 'user' => $this->user]);
    }
}

问题出在哪里?我成功排队作业并收到电子邮件,但收到错误:

Trying to get property 'view' of non-object

堆栈跟踪:https://flareapp.io/share/87nOGYM5#F59

这是我以前的工作代码:

//Provider
ResetPassword::toMailUsing(function ($notifiable, $token) {
    $url = url(route('password.reset', ['token' => $token, 'email' => $notifiable->getEmailForPasswordReset()]));
    return new ResetPasswordMail($url, $notifiable);
});

//Mailable
class ResetPassword extends Mailable
{
    use Queueable, SerializesModels;
    protected $url;
    protected $user;


    public function __construct($url, $user)
    {
        $this->url = $url;
        $this->user = $user;
    }


    public function build()
    {
        $address = 'noreply@' . config('app.domain');
        $name = 'Lorem ipsum';
        $subject = config('app.name') . ' - Próba zresetowania hasła';

        $this->to($this->user)->subject($subject)->from($address, $name)->markdown('emails.password_reset', ['url' => $this->url, 'user' => $this->user]);
    }
}

非常感谢任何帮助。

【问题讨论】:

  • 错误信息告诉你问题出在哪里。您应该将其包含在您的问题中。
  • toMailUsing 不需要返回MailMessage 通知的实例吗?你也不会从闭包中分派工作。

标签: php laravel laravel-queue laravel-mail


【解决方案1】:

这看起来很复杂,所以我不确定你的问题出在哪里。但如果它有帮助,我会这样做以发送排队的自定义密码重置电子邮件。

  1. Illuminate\Auth\Passwords\CanResetPassword::sendPasswordResetNotification()User 模型继承;覆盖它以使用您的自定义通知。

    <?php
    
    namespace App;
    
    use App\Notifications\UserPasswordReset;
    
    class User extends Authenticatable
    {
        public function sendPasswordResetNotification(string $token): void
        {
            $url = route('password.reset', [
                'token' => $token,
                'email' => $this->getEmailForPasswordReset()
            ]);
            $this->notify(new UserPasswordReset($url));
        }
    }
    
  2. 构建自定义通知并确保它是可排队的

    ​​>
    <?php
    
    namespace App\Notifications;
    
    use App\Mail\UserPasswordReset as UserPasswordResetMailable;
    use App\User;
    use Illuminate\Bus\Queueable;
    use Illuminate\Contracts\Queue\ShouldQueue;
    
    class UserPasswordReset extends Notification implements ShouldQueue
    {
        use Queueable;
    
        protected $url;
    
        public function __construct(string $url)
        {
            $this->url = $url;
        }
    
        public function via(User $notifiable)
        {
            return ["mail"];
        }
    
        public function toMail(User $notifiable)
        {
            return new UserPasswordResetMailable($this->url, $notifiable);
        }
    }
    
  3. 您现有的邮件应该可以正常工作,尽管这是我的样子:

    <?php
    
    namespace App\Mail;
    
    use App\User;
    use Illuminate\Bus\Queueable;
    use Illuminate\Mail\Mailable;
    use Illuminate\Queue\SerializesModels;
    
    class UserPasswordReset extends Mailable
    {
        use Queueable;
        use SerializesModels;
    
        public $user;
        public $url;
    
        public function __construct(string $url, User $user)
        {
            $this->user = $user;
            $this->url = $url;
        }
    
        public function build()
        {
            return $this->
                ->with(["message" => $this])
                ->to($this->user->email)
                ->from(config("mail.from.address"))
                ->subject(__("Password Reset"))
                ->text("email.reset_plaintext")
                ->view("email.reset_html");
        }
    }
    

不需要服务提供者,不需要工作类别。

【讨论】:

  • 嗯,这似乎有效,但不确定它是否正确排队 - php artisan queue:listen 没有显示任何内容。 @Edit 真的需要它可以用标记邮寄
  • 说实话,我从来没有过多地研究过它。 The documentation 说“一旦ShouldQueue 接口被添加到您的通知中,您就可以像往常一样发送通知。Laravel 将检测类上的ShouldQueue 接口并自动排队发送通知。”所以我相信他们的话!
  • 如果您想要 Markdown,请将 text()view() 方法替换为 markdown(),或者使用您现有的 Mailable 实例。应该是一样的。
【解决方案2】:

我使用下面的代码在 Laravel 8.x 中发送带有队列的 ResetPassword 邮件

通过php artisan make:notification ResetPasswordNotification 创建新的 ResetPasswordNotification 类并将其代码替换为:

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Auth\Notifications\ResetPassword;

class ResetPasswordNotification extends ResetPassword implements ShouldQueue
{
    use Queueable;
}

并在您的 App\Models\User 类中添加方法 sendPasswordResetNotification 方法:

<?php

...
use App\Notifications\ResetPasswordNotification;
...    

/**
 * Send the password reset notification.
 *
 * @param  string  $token
 * @return void
 */
public function sendPasswordResetNotification($token)
{
    $this->notify(new ResetPasswordNotification($token));
}

然后运行php artisan queue:work 并测试

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-27
    • 2019-12-06
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    • 2016-07-14
    相关资源
    最近更新 更多