LaravelでSMTP経由で複数の送信元メールアカウントを切り替える

こんなよくあるシチュエーションが上手くいかずに苦悩したので備忘も兼ねて

Configオブジェクトの設定を書き換えて送信すればいいよね。
って思ったので


//foo@example.comアカウントで送信
Config::set('mail.username', 'foo@example.com');
Config::set('mail.password', 'barpass');
Mail::raw($body, function($message) {
  $message->to('dest@example.com');
  $message->subject("test");
});

//bar@example.comアカウントで送信
Config::set('mail.username', 'bar@example.com');
Config::set('mail.password', 'barpass');
Mail::raw($body, function($message) {
  $message->to('dest@example.com');
  $message->subject("test");
});

こんな感じに書いた。
ちなみに.envでは
MAIL_USERNAME=hoge@example.com
MAIL_PASSWORD=hogepass
としていた。

このコードを動かしてみると
1回目のメール送信はfoo@example.comアカウントでプログラムした通りに送信してくれる。
ところが、
2回目のメール送信もfoo@example.comアカウントでメール送信してしまう。

原因

この現象を御幣を恐れず簡単に説明すると。
Mailがstaticなので1回目の処理で作られたメールアカウント(transport)を持っていて
2回目はインスタンスがある為に新規にメールアカウント(transport)のインスタンスを作らずに
1回目のメールアカウント(transport)を引き継いで処理してしまう。

回避方法

何かメールアカウントをクリアする方法があるのかと調べましたが見つからず、
どうやらTransportのインスタンスを個別に作らないとだめらしい。

やり方を書いてくださっているページがあったのでリンクさせていただきます。
LaravelのMailで、機能ごとに送信元アドレスを切り替えたい(Gmailなど)時にめっちゃ詰まった話

PHP::PDOでMySQLに接続するときのスニペット

ちょっとしたサンプル書くときにPDO接続するときのオプションなんだったっけ?みたいになるので書き残します。
最近のフレームワークはこの辺の基礎構文書かないから忘れるw

charsetを指定していることで「set names」しなくてよくなる。
PDO::ATTR_ERRMODEでSQLの実行エラーを例外処理
PDO::ATTR_DEFAULT_FETCH_MODEでselect文の実行結果を連想配列(PDO::FETCH_ASSOC)を指定することでfetch()の時にパラメータを省略できる。

$dsn = 'mysql:dbname=placktis;host=127.0.0.1;charset=utf8';
$user = 'root';
$password = '';

try {
    $dbh = new PDO($dsn, $user, $password,[
	    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
	    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]);

} catch (PDOException $e) {
    echo "接続失敗: " . $e->getMessage() . "\n";
    exit();
}
カテゴリー: PHP

laravel artisanコマンド

分類 コマンド 説明
php artisan list コマンドの一覧を表示する
php artisan make:controller -h コマンドのヘルプを表示する
php artisan key:generate encryption key を設定する
php artisan route:list route(経路)の状態を表示する
model php artisan make:model User app/モデルクラスをひな形から生成する
model php artisan make:model User –migration クラスのほかにmigrationファイルも生成する
migration php artisan make:migration create_users_table resource
migration php artisan migrate 未実行のmigrateファイルを実行する
migration php artisan migrate:refresh 追加済みのテーブルを削除して再構築する
migration php artisan migrate:refresh –seed refleshに加え、seederを実行する(databaseSeederに依存)
migration php artisan migrate:rollback 1つ前の状態に戻す
seeder php artisan make:seeder UsersTableSeeder seederファイルを作成
seeder php artisan db:seed seederを実行する
seeder php artisan db:seed –class=UsersTableSeeder 特定のseederを実行する
controller php artisan make:controller HogeController コントローラのひな形を生成する
server php artisan serve
request php artisan make:request UserRegistPost リクエストクラスを生成
provider php artisan make:provider RiakServiceProvider プロバイダクラスを生成
cashe php artisan config:clear キャッシュをクリアする
php artisan make:middleware CheckAge ミドルウェアクラスを生成する
auth php artisan make:auth ユーザ認証のひな形を生成する

composerの概要

composerはPHPにおけるパッケージ管理ツールです。

類似のツールとして
LinuxのYum
PHPのpear
NodeJSのnpm
があげられます。

リポジトリと呼ばれるパッケージが登録されたサーバから、パッケージのダウンロード・インストールを行ってくれます。
また、ダウンロードしたパッケージに必要な依存パッケージも一緒に落としてくれるなど環境作成を楽にしてくれるツールです。

◆composerのインストール(Windows+Xampp環境)
PHPへのpathが通っているコマンドプロンプト(PowerShell)で次のコマンドを実行します。
※composer.pharがphp.exeに依存しているので「xampp\php」で操作するとpathを通しやすくて良いんじゃないかと。

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'e5325b19b381bfd88ce90a5ddb7823406b2a38cff6bb704b0acc289a09c8128d4a8ce2bbafcd1fcbdc38666422fe2806') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"

正常に終了すると
カレントにcomposer.pharが作成されます。

composer.pharはcomposer本体で、PHPプログラムをphar圧縮したものです。
使用する際は

php composer.phar [コマンド]

のように使います

◆composer-setup.phpやcomposer.pharについて
composer-setup.phpがやってることはcomposer.pharをダウンロードしてるだけ。
そしてcomposer.pharは独立したPHPプログラムなのでコピペして好きなところに置いていいっぽい。

もっと言えば、composer.pharがあればわざわざインストールしなくてもcomposer.pharをコピペして使って問題なさそうですね

◆composer.pharを使いやすく(linuxっぽく)
composer.pharをダウンロードして設置しただけだと、composerを実行する際に

php composer.phar [コマンド]

のように書く必要があります。

Linux環境では

composer [コマンド]

で実行できるため、いろいろなサイトで学習するにあたって読み替えが必要になったりしますし、このほうが入力が少なくて便利ですよね。

これを実現する設定をしていきたいと思います。
composer.pharを設置したディレクトリに
composer.batを作成し、次の内容をコピーしてください。

@ECHO OFF
php "%~dp0composer.phar" %*

以上です。

動作確認のために次のコマンドを実行してみてください。

composer -V

composerのバージョンが表示されればOKです。

◆composer.batを理解する

composer.batを準備すると、なぜ

composer [コマンド]

とすることができるのか?を解説してきます。

まず、コマンドプロンプトの挙動として
実行可能ファイルの拡張子(.exe,.com,.batなど)は省略できる。
っという性質があります。

なので、コマンドプロンプトに記述する「composer」とは「composer.bat」を意味します。

composer.batの中の意味は
「%~dp0composer.phar」とはcomposer.batがあるディレクトリのcomposer.phar
「%*」は、composer.batに渡されたパラメータを意味します。

php.exeでcomposer.pharを実行し、comoper.batに渡された引数を丸投げしてます。

composer -V
を実行すると次のように変換されるわけですね
php c:\xampp\php\composer.phar -V

XAMPPのPHPをバージョンアップ(5.6→7.3)

XAMPPのPHPをバージョンアップする(5.5→7.2)を参考にさせていただきました。

変更の目的

うちの環境はmargedocさんのPDT(full)で、PDTとxampp(インストール不要zip版)が抱き合わせになってるやつを使ってます。
執筆時点の最新版でバンドルされてるPHPのバージョンが5.6系だったのですが、EC-CUBE4の実行環境を作りたくて、PHP7.3系にしたかった。

概要

  1. PHP7.3のダウンロード
  2. PHP7.3の導入
  3. xamppの設定ファイル調整
  4. xdebugの更新

詳細

PHP7.3のダウンロード

PHPの公式ダウンロードページから任意のバージョンをダウンロードします。
うちの環境(xampp)は64bitなのでVC15 x64 Thread Safe をダウンロード
もし、XAMPPの32bit版を利用している場合はVC15 x86 Thread Safe をダウンロードしてください。

PHP7.3の導入

xampp/phpを適当な名前に変更
※今回は元のバージョンにちなんでphp_56

ダウンロードしたPHPを解凍してフォルダ名を”php”に変更しxamppフォルダに移動

php_56フォルダからphp.iniをphpフォルダにコピー

xamppの設定ファイル調整

この作業をせずにxamppを起動しようとするとapacheがこけるので気づくと思うけど
xampp/apache/conf/extra/httpd-xampp.conf
の設定がphp5用になってるので修正が必要

#LoadFile "[プロジェクトのパス]/xampp/php/php5ts.dll"
LoadFile "[プロジェクトのパス]/xampp/php/php7ts.dll"
#LoadModule php5_module "[プロジェクトのパス]/xampp/php/php5apache2_4.dll"
LoadModule php7_module "[プロジェクトのパス]/xampp/php/php7apache2_4.dll"

モジュール名をここで変えてしまったので

#<IfModule php5_module>
<IfModule php7_module>

※複数あり

のように修正

xdebugのダウンロード

PHPのバージョンが変わったのでxdebugもバージョンアップする必要があります

xdebug公式から任意のバージョンのdllを落とします。
※今回はphp7.3系で VC15 TSのx64なのでPHP 7.3 VC15 TS (64 bit) をダウンロード

ダウンロードしたファイルをphp_xdebug.dllにリネームして”xampp/php/ext/”配下にコピー

xamppにca証明書を設定

参考:http://nanoappli.com/blog/archives/7992

composer.pharやらsymfony.pharでcurlするときに次のようなエラーが出たときの対処法

cURL error 60: SSL certificate problem: unable to get local issuer certificate

内容的には信頼できるca証明の一覧が無いぞ~!ってことらしい

cacert.pemをダウンロードして、phpのディレクトリ放り込む
php.iniのcurlセクションの「curl.cainfo」にcacert.pemのフルパスを指定する。

[curl]
curl.cainfo = "[PHP_ROOT]cacert.pem"

※私みたいにプロジェクトごとにxammp環境作ってるようなら共通で使いまわす方が楽かも

PS.
念のためcreate.pemについて提供元を確認してみた。
WindowsでCURLでCURLコマンドを落としたとこでした。

pemの内容については
https://curl.haxx.se/docs/caextract.html
で確認できる。

色々あるsymfony2のインストール方法

色々調べてみたところホントに色々な入れ方やらパッケージ?があるみたいなのでとりあえず整理します。

composerを使ったやり方

php composer.phar create-project [パッケージ] [インストール先のpath] [バージョン]

例)php composer.phar create-project symfony/framework-standard-edition /path/to/webroot/Symfony 2.3.0

php composer.phar search [文字列] 

で探してみたけど数が多すぎると全部は出してくれないっぽいので

[パッケージ]と[バージョン]はPagkagistで探す方がいいらしい。

ちなみに、composerはcomposer.jsonってファイルでパッケージ等を設定して

php composer.phar install

ってする方法もあるようで、むしろこっちが一般的?

symphony.pharを使ったやり方

php -r "readfile('https://symfony.com/installer');" > symfony.phar
php symfony.phar [コマンド] [インストール先のpath] [バージョン]

例)
php symfony.phar new symfony2 2.3.0
php symfony.phar demo symfony2 2.3.0

newとdemoの違いはよくわからない。。。

helpを見るには

php symfony.phar

xampp環境でEC-CUBE3開発を少し楽にするコマンドプロンプト起動バッチ

EC-CUBE3ってややこしや(笑

composerや各種ジェネレータの利用などなんだかんだとコマンドプロンプトを使う機会が多いのですが、
xampp環境(zip版)だとpathが通ってないので色々面倒

っということでバッチを作りました。

cmd /k set path=%~dp0xampp\php;%path%

cmd /k
この部分でバッチが勝手に閉じられないように対処

set path=%~dp0xampp\php;%path%
ここでpathを通す作業

set
コマンドプロンプトで環境変数を設定するためのコマンド

set path=
これでPATHを設定しますよ~って意味

%~dp0
これで今いるディレクトリパスが取れるらしくて最後にディレクトリセパレータが入ってます。
例) c:\windows\

xampp\php
ここはバッチを置いたディレクトリからphp.exeまでのPATHですね

;
PATHセパレータ

%path%
「既に登録されてるPATH」=環境変数のを参照する。

つまり
set path=[xampp/phpまでのフルパス];%path%

をしてるってこと。

mysqlにもPATHを通すなら

cmd /k set path=%~dp0xampp\php;%~dp0xampp\mysql\bin;%path%

XAMPPにComposerのインストール

margedocさんのオールインワン等PC内に複数環境を作っている場合の情報とかがなかったので残します。

コマンドプロンプトから次を実行

>cd [xampp/phpのパス]
[xampp/phpのパス]>php  -r "eval('?>'.file_get_contents('https://getcomposer.org/installer'));"
Failed loading \project\ec-cube3\pleiades\xampp\php\ext\\project\ec-cube3\pleiades\xampp\php\ext\php_xdebug.dll
All settings correct for using Composer
Downloading...

Composer (version 1.5.2) successfully installed to: [xampp/phpのパス]\composer.phar
Use it: php composer.phar

こんだけ。

ザックリいうと、composer.pharがphpのパスの通ってるところにあれば良いっぽい

次のコマンドで動作確認

[xampp/phpのパス]>php composer.phar
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.5.2 2017-09-11 16:59:25

Usage:
  command [options] [arguments]

こんなのが表示されればとりあえず動いてるらしい

composerを利用する場合は
↑みたいに

php composer.phar [パラメータ]

カレントが[xampp/phpのパス]以外だと

php [xampp/phpのパス]composer.phar [パラメータ]

ってしなきゃダメ臭い。
すんごい面倒なのでバッチを作る

[xampp/phpのパス]>echo @php "%~dp0composer.phar" %*>composer.bat

これでcomposer.batが作られました。
※[xampp/phpのパス]で実行しないとダメなので注意!
そしてディレクトリ名変更したら修正しなきゃダメなのでこの点も注意!
っても絶対このこと忘れてるよねwww

今後は「php composer.phar」を「composer」って読み替えて使う

カテゴリー: PHP

CakePHP2 Formヘルパーのcheckboxの使えなさときたら。。。

checkboxで複数選択の項目を作る場合、cakephpでは次のように書く説明がよくみられます。

$options = array('foo','var');
$formdata = $_POST['data'][フィールド名];

$this->form->input("フィールド名",
 	array(
 		'type'=>'select',
 		'multiple' => 'checkbox',
 		'div'=>false,
 		'label'=>false,
 		'legend'=>false,
 		'options' = $options,
 		'selected' = $formdata,
	)
);

確かに複数で出力される。

だがしかし!「’div’=>false」が効いてない(´・ω・`)

チェックボックスを横並び出来ないっていう。。。。
ソース追いかけたらdivオプション自体がシカトされてる。

皆どうしてるんだろう???

そもそも$this->form->inputは色々な機能を盛り込んだ$this->form->xxxxのalias的な物
エラーメッセージの出力なども自動でやってくれる便利な子ではあります。
色々共通化した結果の歪がこれなんでしょうね。

けど、CakePHPってこうした落とし穴がところどころ存在して悩まされる。
普通に使うFormヘルパーにもこんな落とし穴作るとかもうダメダメじゃん。。。
何でこんなフレームワークが日本でたくさん使われてるのかマジ理解不能。

さらに今回はフィールド名のところを空にしたり、name属性を調整したりと
ソース踏襲の為にFormヘルパーを使て次のように対応

$options = array('foo','var');
$formdata = $_POST['data'][フィールド名];

$i=0;
foreach($options as $val){
	$checked=false;
	if( $data[フィールド名][$i] == $val ) $checked = true;

	echo '<label>';
	echo $this->Form->input(false,
		array("name"=>"data[フィールド名][$i]","type"=>"checkbox",'label'=>false,'div'=>false,'value'=>$val,"checked"=>$checked));
	echo $val.'</label> ';
	$i++;
}
if(isset($errors[フィールド名])) echo '<div class="error-message">'.$errors[フィールド名][0].'</div>';

第1引数のフィールド名をfalseにして色々な機能をOffにして対応。
とりあえず目的の事は出来た。

で、テストしてたら何故だか直前の入力フィールドのエラーメッセージがこのcheckboxに反映されるという
奇々怪々な現象が発生。

いやね、最初は私がフィールド名を間違って書いたのかと思いましたよ。
けどそうじゃなかった!!

inputメソッドの第1引数にフィールド名を指定して使った後に
inputメソッドの第1引数にfalseを使うと、前者のエラーメッセージを拾い上げてくれる優れもの!
もう失笑です。

‘error’=>false

のオプションを追加して非表示にできたけどもさ。。。
もうほんと、なんだかなぁ~って感じです。

昔から不勉強を棚に上げて「使いにくいから!」とFormヘルパーを使わずにゴリゴリPHPコード書いてたんだけど、
やっぱりその方法が正解のようです。

ちなみにバージョンは2.7.8です。