PPPPPRIQIA Press (プププププリッキアプレス)

by 有限会社プリッキア

web・ホームページ・モバイルサイト制作の横浜にある制作会社PRIQIA(プリッキア)のスタッフブログです。

PHPMailerにハマッタ

投稿者: shimojoカテゴリ: CMS, プログラミングタグ:,

私事ですが、本日は私の誕生日でした。\(^◇^)/

社内の人たちに祝ってもらい、本日のブログネタ完成!
・・・と思ったのですが、写真は撮ってないし、
ブログとしてはちょっと文字数が足りないということで、
前回(2/22)に引き続き、技術系の話をします。

今回は開発者向けのコアな内容にします。
お題はPHPのメール送信ライブラリであるPHPMailer。

事の発端は弊社CMS担当から
「MODxでフォームからメールを送信すると送信者名が文字化けします」
の一言。

私もMODxで組んだフォームからメールを送信したことがありますが、
一度も文字化けが発生したことがありませんでした。

とはいえ実際に文字化けしたメールがある以上調査をせねば
ということでまずは文字化けしたメールを確認。

送信者名が↓の様になっています。

ここに非常に長い名前のメール送信者名\r\n を設定してみます

これを見てピンとくる人もいるかもしれませんが、
どうやら文字化けというより、改行コードがそのまま表示されている模様。
ということでそのあたりを中心に調査開始。

普段メールを使用していても、知っている人は少ないと思いますが、
メールの送信者名は文字をそのまま送っているのではなく、
Base64という方式に変換されて送信されています。
これは送る文字が日本語などであってもすべて英数字+α(64種類)
だけを使用して表すことができるというものです。
たとえば、問題の送信者名を変換すると

=?ISO-2022-JP?B?GyRCJW8hPCVrJUkbKEIgGyRCJW8lcxsoQiAbJEIlSCVsITwlRyUjGyhC?=

といった感じになります。(長いので一部抜粋)

この方式の難点は、64種類であらわすため文字の長さが約33%増加するところで、
メールの規格で定められた“78文字で改行するべき”という規格に簡単に接触し改行が行われます。

ということでこの改行を行っているところを調査すると、以下の記述を発見!

$encoded = addcslashes($str, “\0..\37\177\\\”");

これがなにをしているかというと
文字コードの0~31番(8進数で0~37)と127(8進数で177)と\と”を
文字コードから文字列に変換しますという処理。
改行コード(と再起コード)である10番(と13番)は0~31番に含まれるわけで・・・
しかもマルチバイト文字の場合のみ通るというピンポイント処理。

これを対処するには以下の三つが考えられます。
1.addcslashesの処理を改変する
2.処理を行っているメソッドをオーバーライドする。
3.あきらめて長文にならないようにする。

今回は自分で作成したフォームからの送信なので、
手軽さを考え1の対処をしました。↓

$encoded = addcslashes($str, “\0..\11\13..\14\16..\37\177\\\”");

とりあえず、これで問題なく送信されていますが、
オープンソースのコードは過信してはいけないようです。

と書いたのはいいのですが、つい先日このメールフォームスニペットの
新バージョンが出たようで、その中ではこの問題は対処されているそうですorz
あと一週間くらい早く出してほしかった・・・

嫌にスマートなPHPのswap(値入れ替え)

投稿者: たかおファンカテゴリ: プログラミングタグ:

プログラムルーチン上でswapていうと変数の値の交換を指したりしますが、簡単なのに言語の標準機能として実装されておらず、意外と素直に掛けない場合が多い操作です。
たとえばC言語で書くとこんな感じ。

int a = 100, b = 200;
int _tmp;

_tmp = a;
a = b;
b = _tmp;

たかがこれだけのことに3行も掛かってます。(1行、いや無茶して一文で書く方法もあると思うけど)
こんなことに手間を掛けない為に開発環境によってはマクロ関数が用意されている場合もあったりなかったりです。

変わって、PHPは日ごろから歯がゆい文法ばかり書かされる言語なんですが、swapに関しては一種の感動を覚えました。
実にスマートに書けてしまいます。

$a = 100;
$b = 200;

list($b, $a) = array($a, $b);

かっこよすぎる。。。
さらに2値だけでなく、3値以上の入れ替えも一瞬です。瞬く間です。

$a = 100;
$b = 200;
$c = 300;

list($c, $a, $b) = array($a, $b, $c);

ブラボー!

ここだけ見るとPHPがかっこよく見えますが、他に関してはどうもなじめない俺でした。

foreach of reference valiable

投稿者: たかおファンカテゴリ: プログラミングタグ:
$ary1 = array("hoge", "fuga", "piyo");
$ary2 = array("ほげ", "ふが", "ぴよ");

foreach ($ary1 as &$val) {
	echo $val . ', ';
}

foreach ($ary2 as $val) {
	echo $val . ', ';
}

echo PHP_EOL;
var_dump($ary1, $ary2);
hoge, fuga, piyo, ほげ, ふが, ぴよ,
array(3) {
  [0]=>
  string(4) "hoge"
  [1]=>
  string(4) "fuga"
  [2]=>
  &string(4) "ぴよ"
}
array(3) {
  [0]=>
  string(4) "ほげ"
  [1]=>
  string(4) "ふが"
  [2]=>
  string(4) "ぴよ"
}

Σ(´Д`;)

$ary1 = array("hoge", "fuga", "piyo");
$ary2 = array("ほげ", "ふが", "ぴよ");

foreach ($ary1 as &$val) {
	echo $val . ', ';
}
unset($val);

foreach ($ary2 as $val) {
	echo $val . ', ';
}

echo PHP_EOL;
var_dump($ary1, $ary2);
hoge, fuga, piyo, ほげ, ふが, ぴよ,
array(3) {
  [0]=>
  string(4) "hoge"
  [1]=>
  string(4) "fuga"
  [2]=>
  string(4) "piyo"
}
array(3) {
  [0]=>
  string(4) "ほげ"
  [1]=>
  string(4) "ふが"
  [2]=>
  string(4) "ぴよ"
}

ヽ(´ー`)ノ

Behaviorのsettings

投稿者: たかおファンカテゴリ: プログラミングタグ:,

ビヘイビアのこと。1.2RC2

class HogeBehavior extends ModelBehavior {
	var $settings = array();

	function setup(&$model, $config = array()) {
		$default = array(
			'enabled' => true
		);

		$this->settings[$model->alias] = am($default, $config);
	}

	function beforeSave() {
		// hogehoge
		return true;
	}
}

こんなふうに書いて、モデルでこうしたら

class Fuga extends AppModel {
	$actAs = array('Hoge' => array('enabled' => false));
}

beforeSave()が呼ばれなくなってしまった。他のコールバックメソッドも同じかもしれない。
enabledって名前があやしいようだ。
どういう仕様なんだ?
はやくマニュアルできてくれ!

Set::combineの実力

投稿者: たかおファンカテゴリ: プログラミングタグ:,

★HairStyleモデル

class HairCatalog extends AppModel {
	var $hasAndbelongsToMany = array('HairStyle');
}

★コントローラ内

$data = Set::combine(
	$hair_catalog,
	'HairStyle.{n}.id',
	'HairStyle.{n}.name',
	'HairStyle.{n}.hair_style_type_id'
);

記事の続きを読む »

Get Adobe Flash playerPlugin by wpburn.com wordpress themes