見出し画像

CakePHP メール送信

Cakeでメール送信メソッド作成備忘録。
環境:CakePHP2 Windows PHP5.5.19

システム側AppController.php

前提として

App::uses('Controller', 'Controller');
App::uses('CakeEmail', 'Network/Email');

システムメール送信

AppController.php

/**
    * システムメール送信
    *
    * システムからのメール送信
    *
    * @param array $to Toメールアドレス
    * @param array $cc Ccメールアドレス
    * @param array $contents Viewへ渡すオブジェクト
    * @param string $mail_name 使用するテンプレートの名称
    * @param string $template_base default='base'
    * @return true:正常
    */
    
    protected function sendSystemMail($to, $cc, $contents, $mail_name, $template_base = 'base' ){
        try{
            // MailComp(MailComposition) メール送信用Model
            $this->loadModel('MailComp');
            
            //メール設定情報を取得
            $rec = $this->MailComp->find('first', array(
                      'conditions'     => array(
                          'mail_name'   => $mail_name
                       )
                    ));
                        
             // ない場合はエラーログ
             if(empty($rec)){
                 $this->outputLog(ERROR, 'メール設定マスタに必要な情報がありません。メール' . $mail_body . 'がありません。');
                 return false;
             }
             
             //メール送信
             $from = array(
                 $rec['MailComp']['from_address'] => $rec['MailComp']['from_username']
             ); 
             
             // 'bcc'空であれば' '、存在すればカンマ(,)区切りで抽出代入
             $bcc = ((empty($rec['MailComp']['bcc']) == true) ? '' : explode(',', $rec['MailSetting']['bcc']));
             
             //
             $subject = $this->_replaceContent($rec['MailComp']['subject'], $contents);
             
             $body = $this->_replaceContent($rec['MailComp']['body'], $contents);
             
             $contents['body'] = $body;
             
             // CakeEmailインスタンス生成
             $email = new CakeEmail('default');
             $email->template($rec['MailComp']['template'], $template_base)->viewVars($contents)->to($to)->from($from)->subject($subject);
             
             if(!empty($bcc)){
                 $email->bcc($bcc);
             }
             
             return $email->send();
             
          }catch(Exeption $e){
               $this->outputLog('error', $e);
               return false;
          }

使用メソッド

outputLog() 独自メソッド

AppController.php

/**
 * ログ出力
 * 
 * 指定した内容のログを出力
 * メッセージの先頭にセッションIDを付与、CakeLogを呼び出す
 *
 * @param string $type 'notice', 'info', 'debug', 'warning', 'error', 'critical', 'alert', 'emergency'
 * @param mixed $message 出力内容
 */

protected function outputLog($type, $message){
    
    // debugログ出力設定
    if($type == 'debug' && Configure::read('LOG_OUTPUT_DEBUG') != 1){
        return;
    }
    
    // セッションID取得
    $session_id = isset($this->Session) ? $this->Session->id() : 'null' ;
    
    // ユーザーID取得
    $user_id = 'user_id:*****';
    if(isset($this->Session)){
        $auth = $this->Session->read('Auth');
        if(isset($auth['User'])){
            $user_id = "user_id:" . $auth['User']['id'];
        }else{
            $mail_temp_id = $this->Session->read($this->SESSION_MAIL_TEMP_ID_KEY);
            if(Utils::isNotEmpty($mail_temp_id)){
                $user_id = "mail_temp_id:" . $mail_temp_id;
            }
        }
    }
    
    // バックトレースを取得
    $backTrace = debug_backtrace();
    $file = basename($backTrace[0]['file']);
    $line = '(' . $backTrace[0]['line'] . ')';
    
    if($file == "AppController.php" && isset($backTrace[1]['file'])) {
        $file = basename($backTrace[1]['file']);
        $line = '(' . $backTrace[1]['line'] . ')';
    }
    $message2 = null;
    if($message instanceof Exception) {
        $s = $message->getTrace();
        $message = $message->getMessage();
        $message2 = Utils::arrayToString($s);
    }
    
    $message = '[' . $session_id . ']' . $file . $line . $user_id . ' ' . Utils::arrayToString($message);
    CakeLog::write($type, $message, array(), Configure::read('LOG_WEB'));
    if(!empty($message2)){
        CakeLog::write($type, $message2, array(), Configure::read('LOG_WEB'));
    }
}
    

isset()
変数が宣言されていること、そしてnullとは異なることを検査する。
引数:mixed $var, mixed ...$vars
$var:調べたい変数
$vars:別の変数
戻り値:変数に値が存在してnull以外ならtrue、それ以外はfalseを返す。

isNotEmpty() 独自メソッド

Vendor/Utils.php

 /**
    * NULL又は空文字以外かどうかチェックします
    *
    * @param string||integer $str チェック対象文字
    */
   public static function isNotEmpty($str) {
       return !self::isEmpty($str);
   }     

isEmpty() 独自メソッド

Vendor/Utils.php

/**
    * NULL又は空文字かどうかチェックします
    * empty()の場合、0の場合trueとなるため、代用です
    *
    * @param string||integer $str チェック対象文字
    */
   public static function isEmpty($str) {
       if (!isset($str)) {
           return true;
       }
       if ('string' == gettype($str)) {
       	if ($str == '0000-00-00') {
       		return true;
       	}
           return (0 == strlen($str));
       }
       if ('integer' == gettype($str)) {
           $str = (string) $str;
       }
       return empty($str);
   }

gettype()
変数の型を取得する。
引数:mixed $value
$value:型を調べたい変数。
戻り値:型を示す文字列を返す。

strlen()
文字列の長さを得る。
引数:string $string
$string:長さを調べる文字列
戻り値:成功した場合は文字列の長さ、空の場合は0を返す。

empty()
変数が空であるかどうかを検査する。
引数:mixed $var
$var:チェックする変数
戻り値:存在し、かつ空や0でなければfalse、それ以外はtrueを返す。

explode()
文字列を文字列により分割する。
引数:string $separator, string $string, int $limit = PHP_INT_MAX
$separator:区切り文字列
$string:入力文字列
$limit:返す配列に含まれる要素の数
戻り値:$stringの内容を$separatorで分割した文字列の配列を返す。

CakeEmail
template() :
レンダリングされた本文を使用する場合はテンプレート名をセット
第1引数:ビュー、第2引数:レイアウトを指定
viewVars():
レンダリングされた本文を使用する場合は、
ビューで使用する変数の配列をセット
to():宛先のメールアドレス、または配列
from():送信先のメールアドレス、または配列
subject():メッセージのサブジェクト

debug_backtrace()
バックトレースを生成する。
引数:int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT, int $limit = 0
$options:オプションのビットマスク
$limit:スタックフレームの数を制限する(デフォルトはすべて返す)
戻り値:連想配列を返す。配列の要素は以下。
    function :現在の関数名
    line   :現在の行番号
    file    :現在のファイル名
    class         :現在のクラス名
    object       :現在のオブジェクト
    type     :現在のコール方式 メソッドなら-> 静的なら::
    args     :関数の内部の場合は関数の引数のリスト
            インクルードされたファイル内では
          読み込まれたファイル名

バックトレースとは,実行中のジョブ定義スクリプトが現在停止している位置にどのようにして到達したかを示す情報

basename()
パスの最後にある名前の部分を返す。
引数:string $path, string $suffix = ""
$path:パス
$suffix:サフィックスが一致する場合はカット
戻り値:指定したpathのベース名を返す。

if( $変数 instanceof  オブジェクト)
あるPHP変数が特定のクラスのオブジェクトのインスタンスであるかどうか
調べる。

Exception::getTrace()
例外のスタックトレースを取得する。
引数:無し
戻り値:例外のスタックトレースを配列で返す。

スタックトレースとは、実行中のコンピュータプログラムにエラーが発生した際に、直前に実行していた関数やメソッドなどの履歴を表示すること。

CakeLog::write()
すべての設定されたロガーにメッセージを書き込む。
引数:$level, $message, $scope = array()
$level:作成されたログメッセージのレベル
$message:書き込みたいログメッセージ

Configure::read()
保存したデータを読み込む。
引数:$key = null
$key:読み込むキー

_replaceContent() 独自メソッド

 AppController.php  
 
   /**
    * 置換処理
    *
    * @param string $word 置換対象文字列
    * @param array $contents 置換文字が含まれる配列
    */
 private function _replaceContent($word, $contents){
     
     $pattern = '/(\$\{)([^ \}]*)(\}+?)/':
     $checkBody = $word;
     
     while(true){
         $match = array();
         preg_match($pattern, $checkBody, $match);
         if(empty($match)){
               break;
         }
         
         // ${}を取り除く
         $key = str_replace('${', '', $match[0]);
         $key = str_replace('}', '', $key);
         
         // 変数名、関数名、パラメータの最大3つに分ける
         $params = explode(',', $key);
         
         // 変数名をテーブル名とカラム名に分けて、置換できるかチェック
         $ary = explode('.', $params[0]);
         if(!isset($contents[$ary[0][$ary[1]])){
             $this->outputLog(ERROR, '置換対象文字列に対する文字が設定されていません。[' . $key . ']が置換できません。');
             throw new Exception('置換処理に失敗しました。');
         }
                  
         $val = $contents[$ary[0]][$ary[1]];
         if(1 < count($params)){
             if('number_format' != $params[1] && 'date' != $params[1] && 'youbi' != $params[1]){
                $this->outputLog(ERROR, '置換対象文字列にフォーマットを指定するにはnumber_formatまたはdateまたはyoubiを指定してください。');
                throw new Exception('置換処理に失敗しました。');
             }
         }
         
         $checkBody = str_replace($match[0], $val, $chackBody);
      }
      
      
      $afterBody = $word;
      while(true){
          preg_match($pattern, $afterBody, $match);
          if(empty($match)){
              break;
          }
          // ${}を取り除く
          $key = str_replace('${', '', $match[0]);
          $key = str_replace('}', '', $key);
          
          // 変数名、関数名、パラメータの最大3つに分ける
          $params = explode(',', $key);
          $ary = explode('.', $params[0]);
          // 変数名に一致する値を取得
          $val = $contents[$ary[0]][$ary[1]];
          
          // フォーマットが指定されている場合、変換
          if(1 < count($params)){
              if('number_format' == $params[1]){
                  if(isset($params[2]) && is_numeric($params[2])){
                      $val = number_format($val, $params[2]);
                  }else{
                      $val = number_format($val);
                  }
              }else if('date' == $params[1]){
                  $dateadd = "";
                  // params[3]に日数加算パラメータが入っていた場合、追加
                  if(isset($params[3])){
                      $dateadd = $params[3]." day";
                  }
                  $val = date($params[2], strtotime($val . " " . $dateadd));
              }else if('youbi' == $params[1]){
                  //params[2]に日数加算パラメータが入っていた場合、追加
                  if(isset($params[2])){
                      $val = date("Y/m/d", strtotime($val . " " . $params[2] . " day"));
                  }
                  $dt = new DateTime($val);
                  $val = Utils::getDOW($dt);
              }else{
                  $this->outputLog(ERROR, 'フォーマット変換に失敗しました。');
                  throw new Exception('置換処理に失敗しました。');
              }
           }
           
           $afterBody = str_replace($match[0], $val, $afterBody);
           
        }
        return $afterBody;
      }

preg_match()
正規表現によるマッチングを行う。
引数:string $pattern,string $subject,array &$matches = null,
   int $flags = 0,int$offset = 0
$pattern:検索するパターンを表す文字列
$subject:入力文字列
$matches:検索結果が代入される
$flag:フラグの組み合わせ
$offset:検索の開始位置を指定する
戻り値:マッチした場合1、しない場合0、失敗したらfalseを返す。

str_replace()
検索文字列に一致したすべての文字列を置換する。
引数:array|string $search,array|string $replace,string|array $subject,
   int &$count = null
$search:探したい値。配列を使えば複数の値を指定できる
$replace:見つかった文字列等を置き換える値
$subject:検索・置換の対象となる文字列、または配列
$count:マッチして置換が行われた箇所の個数
戻り値:置換後の文字列か、配列を返す。

count()
変数に含まれるすべての要素、あるいはオブジェクトに含まれる
何かの数を数える。
引数:Countable|array $value, int $mode = COUNT_NORMAL
$value:配列あるいはCountableオブジェクト
$mode:再帰的に配列をカウントするかどうかのオプション
戻り値:要素の数を返す。

number_format()
数字を千の位毎にグループ化してフォーマットする。
引数:float $num,int $decimals = 0,?string $decimal_separator = ".",
   ?string $thousands_separator = ","
$num:フォーマットする数値
$decimals:小数点以下の桁数
$decimal_separator:小数点を表す区切り文字
$thousands_separator:千の位毎の区切り文字
戻り値:フォーマットした結果を返す。

date()
ローカルの日付・時刻を書式化する。
引数:string $format, ?int $timestamp = null
$format:DateTimeInterface::format() が受け入れるフォーマット
$timestamp:Unixタイムスタンプ(デフォルトはtime()の戻り値)
戻り値:日付を表す文字列を返す。

getDOW() 独自メソッド

 Vendor/Utils.php
 
 /**
    * 曜日文字列取得(Datetimeオブジェクト版)
    *
    * 日付より曜日(日本語1文字)を取得します
    *
    * @param dateTime $dt Datetimeオブジェクト
    * @return string 曜日
    */
   public static function getDOW($dt) {
       $dayIndex = self::getDOWIndex($dt);
       $daykStr = self::$_weekArray[$dt->format('w')];
       return $daykStr;
   }

$_weekArray

Vendor/Utils.php

/**
    * 曜日定義
    *
    */
   private static $_weekArray = array(
       '日',
       '月',
       '火',
       '水',
       '木',
       '金',
       '土'
   );

getDOWIndex() 独自メソッド

Vendor/Utils.php

    /**
    * 曜日インデックス値取得(Datetimeオブジェクト版)
    *
    * 日付より曜日のインデックス値(Utils::SUNDAY、Utils::MONDAY・・Utils::SATURDAY)を取得します
    *
    * @param dateTime $dt Datetimeオブジェクト
    * @return int 曜日のインデックス値(Utils::SUNDAY、Utils::MONDAY・・Utils::SATURDAY)
    */
   public static function getDOWIndex($dt) {
       return $dt->format('w');
   }   

DateTime::format()
指定された形式に従ってフォーマットされた日付を返す。
引数:string $format
$format:出力される日付文字列の形式
戻り値:成功するとフォーマットされた日付文字列を返す。

使い方

try{

//何らかの処理

    $user =  $this->Auth->user();
    $user_name = $user['name'];
    $to = $user['mail_address'];
    $mail = $this->loadModel('Mail');
    $template = $mail['thanks_mail'];
	if(empty($to)){
		$this->outputLog(ERROR, $user_name.'へのメール送信に失敗しました。');
	}else{
		$field = $user['name'];
		$res = $this->sendSysMail($to,null,$user_name,$template);
		if(!$res){
			$this->outputLog(ERROR, 'メール送信に失敗しました。');
		}
	}
    
}catch(Exception $e){
 
 // 例外処理
 
}	

①メール送信を同時にしたい何かの処理を走らせる。
 例えば、新規会員登録⇒お礼のメール。
②メール関連のそれぞれの変数に情報を入れる。
③例外処理をしつつ送信する。

以上。

いいなと思ったら応援しよう!