Laravel --- Laravel5.3 和 Workerman結合使用(異步)

網上查閱資料有現成和workerman結合的composer組件,但我的感受不太靠譜,github上star太少,並且怕有問題也很差調,就想本身先試試。php

個人辦法由於修改要一點Workerman源碼,且是直接引入Workerman的代碼文件,感受有點low,但才智有限,暫時沒想到更好的方法。laravel

準備:git

  1.需先了解Laravel框架下命令行的使用,參考中文版教程github

  2.需瞭解Workerman的基本知識json

場景:用戶註冊後,異步方式給用戶發送郵件提醒app

1.把Workerman框架放到app目錄下

2.建立命令代碼:

php artisan make:command SendEmail

 

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Mail\Message;
use Workerman\Worker;

require app_path('Workerman/Workerman_Linux/Autoloader.php');

class SendEmail extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'send:email {action}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     */
    public function handle()
    {
        $mailWorker = new Worker('Text://0.0.0.0:12345');
        $mailWorker->count = 4;
        $mailWorker->name = 'MailWorker';
        $mailWorker->onMessage = function ($connection, $emailData) {
            $emailData = json_decode($emailData);
            $name = $emailData->name;
            $email = $emailData->to;
            Mail::raw('註冊成功', function (Message $message) use ($email) {
                $message->to($email)->subject(trans('mail.welcome_register'));
            });

            // 寫入日誌
            Log::useFiles(storage_path() . '/logs/event.log', 'info');
            Log::info("{$name}({$email})註冊成功");
        };

        Worker::runAll();
    }
}

以上是workerman服務端,用命令行啓動:composer

php artisan send:email start

此時命令行下會報錯:Workerman[artisan] not run,緣由是Workerman會把第一個參數artisan當前啓動文件,而實際上,send:email纔是咱們想要的啓動文件框架

解決:修改Workerman的解析參數代碼異步

Workerman\Workerman_Linux\Worker.php,修改parseCommand方法(只要把$argv的鍵都加1就行):socket

    /**
     * Parse command.
     * php yourfile.php start | stop | restart | reload | status
     *
     * @return void
     */
    protected static function parseCommand()
    {
        global $argv;

        if($argv[0] == 'artisan') // laravel框架下處理
        {
            // Check argv;
            $start_file = $argv[1];

            if (!isset($argv[2])) {
                exit("Usage: php yourfile.php {start|stop|restart|reload|status}\n");
            }

            // Get command.
            $command  = trim($argv[2]);
            $command2 = isset($argv[3]) ? $argv[3] : '';
        }
        else
        {
            // Check argv;
            $start_file = $argv[0];
            if (!isset($argv[1])) {
                exit("Usage: php yourfile.php {start|stop|restart|reload|status}\n");
            }

            // Get command.
            $command = trim($argv[1]);
            $command2 = isset($argv[2]) ? $argv[2] : '';
        }
    
     // 只要略修改上面的參數解析部分便可 
     ..........................
}

 從新啓動OK:

php artisan send:email start

 

3.服務端完成了,下面是客戶端代碼

個人郵件操做代碼是看成事件邏輯,因此在事件監聽器文件寫代碼:

app\Listeners\SendMailEventListener.php:

<?php

namespace App\Listeners;

use App\Events\SendMailEvent;class SendMailEventListener extends BaseEventListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  SendMailEvent $event
     * @return void
     */
    public function handle($event)
    {
        // 發送郵件通知註冊成功
        if ($event->user->scene == 'do_register') {
            $email = $event->user->email;

            //$ip = "mail_worker 的ip" ,本機的話爲127.0.0.1
            $socket = @stream_socket_client('tcp://127.0.0.1:12345', $errno, $errmsg, 5);
            if ($socket) {
                $mail_data = ['name'=>$event->user->name,'to' => $email, 'content' => trans('mail.welcome_register')];
                // 注意,Text協議後面"\n"換行符是必須的
                $mail_buffer = json_encode($mail_data) . "\n";
                // 發送給mail worker
                fwrite($socket, $mail_buffer);
            }

//            $email = $event->user->email;
//            Mail::raw('註冊成功',function (Message $message) use ($email) {
//                $message->to($email)->subject(trans('mail.welcome_register'));
//            });
        }
    }
}

 

4.總結步驟

  啓動服務端---註冊用戶---觸發SendEmail事件---socket客戶端往服務端寫數據---服務端發送郵件

                                    若是各位有更好的結合方式,一塊兒交流下哈。

相關文章
相關標籤/搜索