php 基於yii2框架編寫插件並提交到composer

在yii2框架中基於swiftmailer和redis編寫自定義異步發送郵件的插件,並提交到composer


1、在vendor中創建目錄結構如下:
lvfk 此文件夾下可以由多個插件
└── mailerqueue 插件名稱
    └── src 存放插件源碼
        ├── Mailer.php 繼承\yii\swiftmailer\Mailer,自定參數並正真發送Redis中存儲的郵件
        └── Message.php 繼承\yii\swiftmailer\Message,改寫原有發送郵件功能爲存儲到Redis列表中

2、編寫Mail.php 和 Message.php

Message.php
<?php
/**
 * Message.php.
 * User: lvfk
 * Date: 2018/2/3 0003
 * Time: 16:40
 * Desc:
 */

namespace lvfk\mailerqueue;


use yii\base\InvalidConfigException;

class Message extends \yii\swiftmailer\Message
{
    /**
     * 存儲郵件到redis隊列中
     * @return mixed
     * @throws InvalidConfigException
     */
    public function queue(){
        //檢測redis
        $redis = \Yii::$app->redis;
        if(empty($redis)){
            throw new InvalidConfigException('redis not found in config');
        }

        //檢測mailer
        $mailer = \Yii::$app->mailer;
        if(empty($redis) || !$redis->select($mailer->db) || empty($mailer->key)){
            throw new InvalidConfigException('mailer not found in config');
        }
        if(empty($mailer->key)){
            throw new InvalidConfigException('parameter key not found in mailer config');
        }
        if(!$redis->select($mailer->db)){
            throw new InvalidConfigException('parameter db not found in mailer config');
        }


        //發送
        $message = [];
        $message['from'] = array_keys($this->from);
        $message['to'] = array_keys($this->getTo());
        $message['cc'] = !empty($this->getCc())?array_keys($this->getCc()):[];
        $message['bcc'] = !empty($this->getBcc())?array_keys($this->getBcc()):[];
        $message['reply_to'] = !empty($this->getReplyTo())?array_keys($this->getReplyTo()):[];
        $message['charset'] = $this->getCharset();
        $message['subject'] = $this->getSubject();
        //正文處理
        $parts = $this->getSwiftMessage()->getChildren();
        if(!is_array($parts) || count($parts) == 0){
            $parts = [$this->getSwiftMessage()];
        }
        foreach ($parts as $part){
            if(!$parts instanceof \Swift_Mime_Attachment){//判斷是否爲附件
                switch ($part->getContentType()){//判斷內容格式
                    case "text/html":
                        $message['html_body'] = $part->getBody();
                        break;
                    case "text/plain":
                        $message['text_body'] = $part->getBody();
                        break;
                }
            }
            if(!empty($message['charset'])){
                $message['charset'] = $part->getCharset();
            }
        }

        return $redis->rpush($mailer->key, json_encode($message));
    }
}
Mail.php 
<?php
/**
 * Mailer.php.
 * User: lvfk
 * Date: 2018/2/3 0003
 * Time: 17:06
 * Desc:
 */

namespace lvfk\mailerqueue;


use yii\base\InvalidConfigException;
use yii\web\ServerErrorHttpException;

class Mailer extends \yii\swiftmailer\Mailer
{
    //指定到我們自定義的Message類
    public $messageClass = 'lvfk\mailerqueue\Message';

    public $db = '0';//默認爲redis第0個數據庫

    public $key = 'mails';//默認爲redis的存儲隊列名字

    /**
     * 設置數據
     * @param $messageObj
     * @param $message
     * @return bool
     */
    private function setMessage($messageObj, $message){
        if (empty($messageObj)) {
            return false;
        }
        if (!empty($message['from']) && !empty($message['to'])) {
            $messageObj->setFrom($message['from'])->setTo($message['to']);
            if (!empty($message['cc'])) {
                $messageObj->setCc($message['cc']);
            }
            if (!empty($message['bcc'])) {
                $messageObj->setBcc($message['bcc']);
            }
            if (!empty($message['reply_to'])) {
                $messageObj->setReplyTo($message['reply_to']);
            }
            if (!empty($message['charset'])) {
                $messageObj->setCharset($message['charset']);
            }
            if (!empty($message['subject'])) {
                $messageObj->setSubject($message['subject']);
            }
            if (!empty($message['html_body'])) {
                $messageObj->setHtmlBody($message['html_body']);
            }
            if (!empty($message['text_body'])) {
                $messageObj->setTextBody($message['text_body']);
            }
            return $messageObj;
        }
        return false;
    }

    /**
     * 發郵件
     */
    public function process(){
        //檢測redis
        $redis = \Yii::$app->redis;
        if(empty($redis)){
            throw new InvalidConfigException('redis not found in config');
        }
        //獲取郵件列表,併發送
        if($redis->select($this->db) && $messages = $redis->lrange($this->key, 0, -1)){
            $messageObj = new Message();
            foreach ($messages as $message){
                $message = json_decode($message, true);
                if(empty($message) || !$this->setMessage($messageObj, $message)){
                    throw new ServerErrorHttpException('message error');
                }
                if($messageObj->send()){//發送成功之後,刪除隊列中數據
                    $redis->lrem($this->key, -1, json_encode($message));
                }
            }
        }

        return true;
    }
}

3、在web.php中配置,業務代碼中即可使用自定義插件

'aliases' => [//在配置添加,實現mailer中class可以找到我們的自定義插件類
	'@lvfk/mailerqueue' => '@vendor/lvfk/mailerqueue/src'
],

以下兩個在components數組中配置:
//自定義mailer組件
'mailer' => [
	'class' => 'lvfk\mailerqueue\Mailer',
	'db' => 9,//設置redis使用庫
	'key' => 'mails',//redis 列表名字
	'useFileTransport' => false,
	'transport' => [
		'class' => 'Swift_SmtpTransport',
		'host' => 'smtp.163.com',
		'username' => '[email protected]',
		'password' => 'xxxx',
		'port' => '465',
		'encryption' => 'ssl',
	],
],

//redis 操作組件配置
'redis' => [
	'class' => 'yii\redis\Connection',
	'hostname' => 'localhost',
	'port' => 6379,
	'database' => 9,
	'password'  => '123456',
],
4、業務代碼中調用
//先發送到redis,異步發送
\Yii::$app->mailer->compose('reply', [
	'username'=>$username,
	'userpass'=>$userpass,
	'useremail'=>$this->useremail,
	'time'=>$time,
	'token'=>$token
])
->setSubject('電子郵箱註冊激活')
->setFrom(['[email protected]'=>'lvfk'])
->setTo($this->useremail)
->queue();
5、異步發送,使用yii2的commands命令
5.1、由於yii2的command命令使用的是配置console.php而不是web.php,因此要把第3步中的三個配置移到console.php中
5.2、在commands編寫文件MailerController.php
class MailerController extends Controller
{
    /**
     * 發送郵件
     */
    public function actionSend()
    {
        \Yii::$app->mailer->process();
        var_dump('發送完畢');
    }
}
5.3、發送
在項目更目錄中執行:./yii mailer/send

6、利用crontab任務定時發送郵件
*/3 * * * * /var/www/yii2/yii mailer /send >> /var/log/mailer.log

7、插件提交composer
7.1、在github網站上新建一個新庫yii2_mailerqueue
7.2、把新庫克隆到本地
git clone https://github.com/Justshunjian/yii2_mailerqueue.git
7.3、把插件src複製到克隆到本地的yii2_mailerqueue
cp -r /var/www/yii2-shop/vendor/lvfk/mailerqueue/src/ yii2_mailerqueue/
7.4、編寫composer.json
{
	"name": "lvfk/mailerqueue",
	"type": "yii2-extension",
	"description": " async mailer by swiftmailer and redis base on yii2",
	"keywords": ["yii2","redis","async","mailer"],
	"license": "MIT",
	"support": {
		"issues":"https://github.com/Justshunjian/yii2_mailerqueue/issues",
		"forum":"",
		"source":"https://github.com/Justshunjian/yii2_mailerqueue"
	},
	"authors":[
		{
			"name":"lvfk",
			"email":"[email protected]"
		}
	],
	"require":{
		"yiisoft/yii2":"*",
		"yiisoft/yii2-redis":"~2.0.0"
	},
	"autoload":{
		"psr-4":{
			"lvfk\\mailerqueue\\":"src/"
		}
	}
}
7.5、提交到github
7.6、進入composer官網https://packagist.org/,使用github帳號登錄
7.7、登錄成功之後,點擊右上角submit
A、把待提交項目github的地址拷貝到網頁文本框
https://github.com/Justshunjian/yii2_mailerqueue.git

B、經過A就已經提交成功,但是在頁面上還需要根據提示設置當github更新之後,composer這步數據自動更新

curl -XPOST -H'content-type:application/json' 'https://packagist.org/api/update-package?username=Justshunjian&apiToken=TOKEN' -d'{"repository":{"url":"https://github.com/Justshunjian/yii2_mailerqueue.git"}}'
其中TOKEN在Profile中的Your API Token中隱藏的

8、下載安裝並使用
8.1、下載安裝
composer require lvfk/mailerqueue

8.2、配置有微調,業務代碼使用無需調整
由於是下載安裝的,因此配置文件中的3個配置中別名設置aliases不用設置了,因爲是composer自動加載的,只需保留
以下兩個在components數組中配置:
//自定義mailer組件
'mailer' => [
	'class' => 'lvfk\mailerqueue\Mailer',
	'db' => 9,//設置redis使用庫
	'key' => 'mails',//redis 列表名字
	'useFileTransport' => false,
	'transport' => [
		'class' => 'Swift_SmtpTransport',
		'host' => 'smtp.163.com',
		'username' => '[email protected]',
		'password' => 'xxxx',
		'port' => '465',
		'encryption' => 'ssl',
	],
],

//redis 操作組件配置
'redis' => [
	'class' => 'yii\redis\Connection',
	'hostname' => 'localhost',
	'port' => 6379,
	'database' => 9,
	'password'  => '123456',
],
9、完成



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章