Home > PHP

PHP Archive

さよならPHP

  • 2011-04-01 (金)
  • PHP
この記事の所要時間: 324
このエントリはエイプリルフールに掲載した空想のお話です。
僕は今日もきっとPHPと一緒です。

君と出会ったのはいつだったかな。

あらためてそんなことを思い出すこともないくらいいつも一緒にいるね。

そう僕らはいつも一緒にいるんだ。

あれはまさにITバブル真っ盛りの2000年。僕はWebでシステムを作ることを夢見てパートナーを探していた。

誰がいたかな、ああ真珠に良く似た名前の子もいたし、蛇みたいな子もいた。

赤い宝石みたいな子はその時はあまり見かけなかったかな。

そんな中に君がいたんだ。

僕らはすぐに意気投合した。一緒に色んなWebシステムを作り上げてきたね。

今だからいうけど、実は君の$は嫌いだったんだ。

はじめは、もうあれを見ると生理的にダメだった。真珠っちもそこがイマイチだったんだよな。

でも「あばたもえくぼ」とは良く言ったもので一緒にいる時間が長くなると、そんなことは気にならなくなった。

いつしか変数入力しようとすると、とっさに左親指がshiftキーに動くようになった。

おかげでたまに他の子と遊ぶ時もついつい$を打ってしまうよ。

人って慣れていくもんだね。

僕は知ってるよ。

今でこそ他の子たちと付き合ってるやつらから、やいのやいのとやっかみを言われてるけど、あの頃は違った。

あの頃は、これからのWebシステム言語として君が注目されていたのを。

実際、僕も君と付き合っていたおかげで色んな人に声をかけられたものさ。

自分のことを褒められているわけじゃないけど、なんだか嬉しかったよ。

もちろん分かってるさ。結局大事なのは言語じゃなくて、それを使う人自身だってことは。

でもその時は君といるだけで、周りの見る目は違ったんだ。

いつの頃からだろう、周りの目が変わったのは。

時は流れて、状況は変わっていく。それは当たり前のこと。特に進化が早いって言われてるWebの世界ではね。

もちろん君も変わっていった。他の子の良いところをどんどん取り入れようと努力していたね。

オブジェクト指向、アクセス制御子、例外、そして最近は、名前空間にクロージャかな。

でも、そんななりふり構わずどん欲に他の子の良いところを取り込んでいく姿勢が反感を買ってしまったのかな。

最近のWebを見ると、君のことを蔑むような発言が多くなった。

もちろん、最初はそんなこと気にしてなかったよ。

arrayばかり書かされるだの、引数の順番に統一性が無いだの、後付けオブジェクト指向だの色々言われても、そんなこと気にしてなかった。

もちろん気になるところはあったけど、僕らはあの手この手で上手くやってきたしね。

でも、いつしかその発言は君と一緒にいる僕らにも向けられるようになった。

謂われのない誹謗中傷。

君と一緒にいる僕らは人それぞれ違うのに、なぜか一緒にされる。

ラベル付けされて、攻撃される。。。

分かってるよ。僕らの間で何かがあったわけじゃない。そう、多分僕らはこれからも上手くやっていけるよ。

でも、

でも、

でも、

僕はもう限界なんだ。。。。。。。。。

こんなこと言うと君はなんて言うかな。

いつもみたいに「Notice: Undefined variable」って言うかな。

怒って「Fatal error !」って言うかも。

ああ、あきれて「Parse error: syntax error」かな。

君が悪いんじゃない。僕が負けたんだ。

君のことはずっと忘れない。

でも、ちゃんと言わせて。今日、そう今日しか言えないんだ。

「さよならPHP」

via. Big Sky :: さよならIE6たん

PHPカンファレンス関西を2011/04/02に開催します

この記事の所要時間: 420

申し込み受付開始しました!PHPカンファレンス関西サイトからお申し込みください。
PHPカンファレンス関西サイト

2011/04/02に大阪で「PHPカンファレンス関西」というイベントを開催します。

昨年末からイベントや直接お会いした人にはお話していたのですが、PHPカンファレンス関西というイベントを開催します。

東京でもう11年も開催されているPHPカンファレンスようなイベントをぜひ関西でやってみたいということで企画しています。

PHPカンファレンスを関西で!

PHPカンファレンスは、国内最大のPHPイベントで、毎年東京で開催されています。

国内・海外のPHPに精通する識者たちが発表を行うイベントで毎年数百人の参加者が集まります。おそらく関東近郊のPHPユーザの方なら一度は参加したことがあるでしょう。(まだの方はぜひ参加してみてください)

私は関西在住なのですが、これまで何度か参加したことがあります(発表も!)。初めて参加した時は、日頃ネットや本の上でしか知ることができなかった技術について、実際の活用事例を交えてお話が聞けたことに感銘を受けました。実際にその技術を使っている人が、そこにいるというリアリティを感じられる貴重な機会でした。

もちろん勉強会でもそういった経験はできるわけですが、PHPカンファレンスのような大きなイベントで受ける印象とはまた異なるものです。単純に大きなイベントならではのお祭り感もありますし、参加人数も多く、会場も広いので気軽に参加できるというメリットもあります。

こういったイベントをきっかけに技術力が向上したり、新たな視点を発見したり、社外の人との交流が増えたりなどして、自身の視野・活動の幅が広がった人も多いのではないでしょうか。

何度かPHPカンファレンスに参加するうちに、こういったイベントをぜひ関西でやってみたいという気持ちが強くなってきました。

関西ではPHPを使っている人がたくさんいるのですが、勉強会は近年それほど開催されていません。関西のPHPユーザが勉強会のようなイベントに興味が無いかというと、そうではなく、PHPやCakePHPの勉強会を開催すると多くの方が参加されます。PHPユーザも多く、勉強会に興味がある人もいるのに、なぜかイベント開催が少ないというのが現状です。

せっかく興味があって意欲がある人が多いのにこういった場が無いというのは勿体無いことです。

また、これまでこういったイベントに興味が無かった人でも地元関西で開催されれば、足を運んでみようという人がいるかもしれません。一度こういったイベントに参加して、何かの刺激を受ければ、一歩先に進めるきっかけになるのではと思います。

私自身もこういったイベントに参加するようになり、多くの人達との交流を持つことで成長できましたし、何より視野が一気に広がりました。いまWeb上で上がっている最新技術動向も遠いあちらの世界で起こっていることではなく、あくまで自分の延長線上にあるものという感覚を持つことができました。

そういった感覚を味わえる「場」を身近な関西で作りたいと考えています。

開催概要

・日時:2011/04/02(土) 10:30〜16:30(10:00開場)
・会場:大阪産業創造館イベントホール
・参加費用:無料(の予定)
・テーマ:「クラウド」「ソーシャルアプリ」「スマートフォン」時代のPHP 
・参加申込:事前登録制(検討中)

2011/04/02に大阪産業創造館(産創館)で開催します。イベントホールを借りているので200人くらいの規模を想定しています。

参加費用は検討中ですが、できれば無料にしたいです。

会場は一つなので、おそらく1トラックで発表を行う形式になります。LT枠なんかも作りたいですね。

テーマは“「クラウド」「ソーシャルアプリ」「スマートフォン」時代のPHP”です。
3つのキーワードをあげていますが、どれもここ1,2年で盛り上がりを見せており、2011年は本格的な利用が進むことが予想されています。そんな時代にPHPはどうあるべきか、どう活用していけば良いかといった内容を盛りこんでいければと思います。もちろん全てのセッションがこのテーマに沿うものというわけではなく、他にも多様なセッションを考えるつもりです。

参加方法ですが、事前登録制になる予定です。こちらは準備が出来次第、告知します。

おそらくPHPのイベントでは関西初の大型イベントになると思うので、PHPに興味がある方はまずは4/2の予定を確保してお待ちください:D

スタッフ募集中!

そんなPHPカンファレンス関西の運営にご協力頂けるスタッフを募集しています。

正直まだまだこれからやらなきゃいけないタスクが山積みですので、こういったイベントの運営に協力したい!という方がいれば shin1x1 [at] gmail.com へご連絡下さい。

まずは公式サイトを立ち上げようと思うので、サイトデザインができる方がいればぜひお願いしますm(_ _)m

多数のご応募ありがとうございました!一旦締め切ります。

PHP Advent Calendar jp 2010 まとめ

この記事の所要時間: 539

PHP Advent Calendar jp 2010が終了しました。

shin1x1から、ラストのrnskさんまで、24日間24名が毎日(若干日がずれたり、前後したりしたことはありましたが;-p)PHPに関するエントリをblogに書いていきました。

参加されたみなさん本当にありがとうございました&お疲れ様でした。

技術系Advent Calendarに参加すること自体が今年初だったのですが、やってみて色々感じたことをつらつらと。

感じたこと

担当日の緊張感(締切りのあるblogエントリ)

言いだしっぺなので初日が当番だったわけですが、何がなんでもその日に書かなきゃいけないというのは良い緊張感でした。

blogを書くというのは、なんだかんだ言ってパワーがいるわけです。とくに忙しい時期だと書きたいことはあってもなかなか書き出せない。もし書き出してもなんかしっくりこずにそのままお蔵入りになることがあったりします。

ただ今回に関しては締切りがあるのでとにかく書いてアップします。

やっぱり最後まで仕上げてアウトプットするとスッキリします。中途半端で終わるより精神衛生上良いですね。

ちょうどCakePHP Advent Calendarも参加しており、2日連続でエントリを書くことになったのですが、大変でしたけどちょっと祭り気分で楽しかったです。

担当日が終わった後がちょっと寂しい

担当日が終わって、CakePHP Advent Calendarの分も書き終えた後は、もう自分の番は回ってこないのでちょっと寂しかったです:D

いちおう主催なので担当日表を作ったり、担当の方にリマインドしたりと事務作業的なことをやりつつ、見守る日が続きました。

担当日にアップするには

見ていて感じたのは担当日に書きだす人が多いのかなーと思いました。

もちろんそれは書く人の自由なので担当日にエントリをアップできれば問題無いのですが、担当日*当日*に書かなきゃいけないわけではないので、担当日に予定がある場合は少し余裕を持って前日までに書いてしまって、当日は修正+アップだけにする方が楽ですね。(締切りギリギリのプレッシャーを受けて書くのも悪く無いですけどね:D)

いちおう主催する側としては、担当の方が書いてもらえるまで結構気を揉んで見守ったりしていたので、早めに書いてもらえると嬉しかったりします。

とにかく完走できて良かった:D

これが今の率直な感想です。当日に書けていない日が2日ありましたけど、まあ初回ということでいちおう完走とさせて下さい。

次回があるかは分かりませんが、次は担当日に書けなかったら焼肉奢りとかにしましょう:D

PHP Advent Calendar jp 2010 エントリ

ATNDのコメント欄に並んでいますが、こちらでも一覧にしました。

あらためて振り返ると色々なネタがありますね。PHP言語や関数以外にもライブラリやフレームワーク、マニュアル、php.net、経験話、そしてネタと多様なエントリがありました。

12/1
12/2 shin1x1 PHP シリアライズデータ型(PHP Advent Calendar jp 2010 Day 2) – Shin x blog
12/3 ikeeki 25行で書いたwebテキストメモ。
12/4 terakuma CodeIgniterを試しに使ってもらう手っ取り早い1つの方法(PHP Advent Calendar jp 2010 Day 4)
12/5 redsnow PHPでxmlを簡単に扱う(PHP Advent Calendar jp 2010 Day 4)
12/6 slywalker PHPでEmoji4Unicodeを使ってみる (PHP Advent Calendar jp 2010 Day 6) – 忍び歩く男 – SLYWALKER
12/7 msng PHPを始めたばかりのころ自分なりにやってた工夫と、それこうした方がいいんじゃないのという提案 – 頭ん中
12/8 sotarok 名前空間とautoload、標準的なClassLoaderの実装 – 肉とご飯と甘いもの @ sotarok
12/9 slumbers99 今更きけないあの娘の名前 (PHP Advent Calendar jp 2010 Day 9)
12/10 fm1202 CURLよりfile_get_contents()
12/11 yuyak PHPマニュアルを読み解く – Yuyak Blog
12/12 gusagi (非フレームワークの)PHPで携帯対応( #phpadvent2010 )
12/13 cakephper.ichikaway 「睡眠学習的PHPer生活 (PHP Advent Calendar 2010 13日目)」
12/14 camelmasa ソーシャルなサービスを支援 (PHP Advent Calendar 2010 14日目)
12/15 tohokuaiki proc_openの64kbの壁「slymak、それfile_get_contentsネタやない、proc_openや」
12/16 wokamoto 匿名関数と無名関数 (PHP Advent Calendar 2010 16日目)
12/17 koyhoge PDO_pgsqlでハマった件 (PHP Advent Calendar 2010 17日目)
12/18 heavenshell Introduction of Net_KyotoTycoon_Rest
12/19 hamaco Sabelを試しつつバッチ処理を作ってみる (PHP Advent Calendar jp 2010 Day 19)
12/20 omoon phpで配列を扱う時のあれこれ ( #phpadvent2010 Day 20 )
12/21 ecworks_masap 【PHP/CakePHP】phpadvent2010 Day21「ピュアPHPでも便利なCakePHPを使おう」
12/22 kashioka 0.1+0.7 =? 小数点について(PHP Advent Calendar jp 2010 Day22)
12/23 kanonji phpのDOMDocumentで断片的なhtmlを扱うならxmlとして読み込むのがよさそう(PHP Advent Calendar jp 2010 Day 23++)
12/24 m-takagi Exploring php.net – m-takagiの日記
12/25 rnsk [実験] PHP関数でiPhoneアプリを作ろう!

Merry X’mas!!

CakePHP Modelとの付き合い方(CakePHP Advent Calendar 2010 3日目)

この記事の所要時間: 612

CakePHPのModelに悩む人が多いようなので、自分なりの付き合い方(考え方)をご紹介します。

CakePHP Advent Calendar 2010の3日目です。

前日の k1LoW さんのエントリ、参考になりますね。GETのフォームをdata[]でやるとURLがすんごいことになるので、ウチでは別途対応できるライブラリを作ったりしてます。

さて、3日目の今日は書きたいネタは幾つかあったのですが、「君の当たり前に僕らは感嘆させられるんだ」の精神に従って、自分なりのModelの使い方、考え方を書いてみます。

1. 適正なインターフェイスを用意して処理をカプセル化

まず基本的な考え方。

Model(に限らずですが)では、処理単位でインターフェイス(メソッド)を用意して、実装はカプセル化しておきます。

こうすることによって、Modelを利用する側(Controllerや他のModel等)はそのインターフェイス越しに処理を呼び出せば、求める処理が実行され、その結果を得ることできます。

呼び出し側では、求める処理さえが実行されれば良いわけで、その処理自体がどのような実装になっているのかは知る必要がありません。極端な話、求める要件さえ満たせば、処理はどのように行われていても良いわけです。

この処理のカプセル化というのはオブジェクト指向では一般的な考え方ですが、あらためてしっかりとイメージしておくとフレームワークと上手く付き合う方法が見えてくるのかなと思います。

もちろん、これはベースの考え方であって、実際は当然実装も気にしますし、それに応じた呼び出し方も考えます。ただ根底ではこの考え方を意識しています。

2. SQLを直接書いて良いか?

CakePHPが用意しているインターフェイスで簡単に全てのクエリが表現できればそれに超したことは無いのですが、実際のところそうもいかないこともあります。

発行したいSQLはイメージできているのに、それをどうCake風に書けば良いかを悩む、という場面に遭遇した人も多いのではないでしょうか。

もちろんフレームワーク流の書き方を習得する方法も1つなのですが、場合によっては、その処理をメソッド内に閉じ込めておけば、SQLを書いてしまっても良いと思います。

イメージとしては以下。このメソッドを呼び出す側からはregisterという処理を実行してくれれば良いわけで、中でsaveメソッドを呼ぶのか、SQL直書きなのかは関係ありません。

  public function register() {
     $this->query('複雑なSQL書く');
  }

もちろん、これも程度の問題で、基本はModelのメソッドをそのまま使います。ただ複雑なSQL、パフォーマンスが要求されるような箇所では、SQL直書きも許容するということです。

3. belongsTo以外のアソシエーションは使わない

単純なbelongsTo以外のアソシエーションは原則使いません。

複数テーブルのJOINが必要な場合は、DBにViewTable(CREATE VIEW)を作成して、それに対応するModelを作ります。

例えばでは、usersテーブルとuser_classesテーブルをJOINしたViewTableを作ります。

CREATE VIEW v_users AS
SELECT
  u.*,
  uc.name AS user_class_name
FROM
  users AS u
JOIN
  user_classes AS uc ON (u.user_class_id=uc.id)
;

そして、v_usersを利用するModelを作ります。

class VUser extends AppModel {
  public $useTable = 'v_users';
}

VUserモデルでfind()等を実行する場合は、あくまでv_usersという一つのViewTableに対する操作となるので、とても単純です。

さらにViewTableは自分でSQLを書いて作るので、意図したとおりのSQLが発行できます。もしクエリをチューニングするときはSQLレベルで調整できます。

複雑なアソシエーションを覚える、制御する必要が無いので、個人的にはこの方法が気にいっています。

4. アクション毎にModelを作る

Modelには多くの責務があるので、アプリケーションが大きくなってくると1つのModelに処理が増えてきて肥大化する傾向があります。

特にバリデーションなどは画面によって内容が異なる場合もあるので、1つのModelにあらゆる場面での処理を書いていくと複雑になり、メンテナンス性が落ちます。

そこで、処理を分割する、1つのModelの責任を小さくするためにControllerのアクション毎にModelを作成しています。

例えば、UserController#index()ならActionUserIndexというModelを、UserController#edit()ならActionUserEditというModelを作成します。

画面毎の処理はそのModelに書き、共通で利用するような処理はUserモデルに書くというように使い分けています。

もちろん中にはUserモデルをfindするだけで済むような画面もあるので、そういう場合は作らないときもありますが、基本的には作成するようにしています。

これにより画面毎の処理を局所化できるので、特にチームでの開発では効率が上がりました。

5. 例外を積極的に使う

わりと敬遠されがちな例外ですが、積極的に使ってます。例外を使えば、処理の考え方がシンプルになります。

例えば、Modelで何かエラーがあったら例外を投げるようにしています。投げる例外は場面に応じたものを選択しますが、とりあえずエラーなら例外を投げるというルールにします。

また、呼び出し側では、try句の中には正常系だけ書いて、異常系はcatchに書きます。try句の中には正常系処理しか無いので、本来実行すべき処理を追いやすくなります。

もちろん例外を使わず戻り値の規約を作れば同じようなことはできますが、try/catch句のようにPHPの構文で実装の意図を明確にすることができます。

try {
  正常系処理
} catch (NotFoundException $e) {
  異常系処理1
} catch (AppException $e) {
  異常系処理2
}

バランスも大事

フレームワークを使う上で、どこまでフレームワークの仕様に合わせるか、どこからは独自の方法で実装するかというのは悩むポイントですね。

このエントリで紹介した内容はCakePHPの基本的な使い方からは少し外れるものもあります。

ただ、フレームワークを使う目的は、フレームワークを使うことではなく、フレームワークを使って何かを作ることだと思っているので、バランスを取りながらうまく付き合っていきたいですね。

CakePHP Advent Calendar 2010 4日目は、remoreさんです。どんなエントリになるか楽しみですね!

PHP シリアライズデータ型(PHP Advent Calendar jp 2010 Day 2)

  • 2010-12-02 (木)
  • PHP
この記事の所要時間: 559

今年(2010年)は、日本でも技術系コミュニティのAdvent Calendarが流行していますね。

PHP関連だとCakePHP(明日書きます!)やSymfonyOpenPNEなどはあるのですが、PHP単体が無かったので作ってみました。

PHP Advent Calendar jp 2010

Advent Calendarについては、下記リンクが詳しいです。これを書いている段階では、まだ参加枠があるので、どんどん参加して下さい。みんなのちょっとしたPHPネタを書いていきましょう!

というわけで、まず初回(12/2に始めたので、Day1は空席で)のネタは、最近自分の中で流行中のPHPのシリアライズデータ(serialize()/unserialize())について。

シリアライズデータのデータ型

CakePHPのセキュリティホール発覚以降、一部で脚光を浴びたPHPのシリアライズなのですが、シリアライズデータで表現できるデータ型をあらためて調べてみました。

まあPHPのソース見れば一目瞭然ですね。

[ext/standard/var_unserializer.c]

 437   case 'C':
 438   case 'O': goto yy13;
 439   case 'N': goto yy5;
 440   case 'R': goto yy2;
 441   case 'S': goto yy10;
 442   case 'a': goto yy11;
 443   case 'b': goto yy6;
 444   case 'd': goto yy8;
 445   case 'i': goto yy7;
 446   case 'o': goto yy12;
 447   case 'r': goto yy4;
 448   case 's': goto yy9;

ざっくり読んだ感じでは以下な内容でしょうか。

C=CustomObject
O=Object
N=NULL
R=Reference
S=string
a=array
b=boolean
d=double
i=integer
o=Objectっぽいけどなんだろ?
r=Reference
s=string

シリアライズデータで表現してみる

‘b’ = boolean

boolean(論理型)です。

b:の後ろの数値は、1ならtrue、それ以外ならfalseになるようです。

b:1; => bool(true)
b:0; => bool(false)

‘i’ = integer

integer(整数型)です。

i:100; => int(100)

‘d’ = double/float

double/float(浮動小数点数)です。

d:10.123; =>float(10.123)

‘s’ / ‘S’ = string

string(文字列)です。’s’と’S’の違いはよく分かってないのですが、文字列をserialize()すると’s’になります。

s(S):の後ろが文字列のバイト数で、””で文字列を囲みます。

s:3:"abc"; => string(3) "abc"
S:3:"abc"; => string(3) "abc"
s:9:"頑張る"; => string(9) "頑張る"(UTF-8)

‘N’ => NULL

NULLです。

N; => NULL

‘a’ => array

array(配列)です。

a:の後ろは要素数です。あとは添え字、要素によって様々な形式を記載します。

a:2:{s:3:"1st";i:100;s:3:"2nd";i:200;}; => 
array(2) {
  ["1st"]=>
  int(100)
  ["2nd"]=>
  int(200)
}

‘C’ / ‘O’ / ‘o’=Custom Object / Object / Object?

クラスインスタンス(オブジェクト)です。通常インスタンスをserialize()すれば、’O’となります。

O:3:"Foo":1:{s:4:"var1";s:3:"abc";}

‘C’は、シリアライズする対象クラスがSerializableをimplementしている時に付与されます。この場合、シリアライズ、デシリアライズ処理は、PHPデフォルトの処理ではなく、対象クラスのserialize/unserializeメソッドで定義された処理が実行されます。

serializeメソッドではシリアライズしたデータをreturnします。unserializeメソッドでは、シリアライズしたデータが引数で渡されるのでそれをパースしてインスタンス変数にセットします。

C:3:"Foo":29:{a:1:{s:6:"value1";s:3:"abc";}}

‘o’は、内部的にはインスタンスを復元するようなのですが、具体的にどのように記載すれば良いかまだ分かってません><

‘r’ / ‘R’ = Reference

Reference(参照)です。’r’(小文字)と’R’(大文字)でデシリアライズした時の挙動が変わります。

‘R’の場合は、参照型としてデシリアライズされます。

a:2:{s:3:"1st";i:100;s:3:"2nd";R:2;}; => 
array(2) {
  ["1st"]=>
  &int(100)
  ["2nd"]=>
  &int(100)
}

‘r’の場合は、変数に参照先の値がセットされますが、参照型にはなりません。

a:2:{s:3:"1st";i:100;s:3:"2nd";r:2;}; => 
array(2) {
  ["1st"]=>
  int(100)
  ["2nd"]=>
  int(100)
}

参照型変数をシリアライズした際は、参照先の変数も一緒にシリアライズされれば’R’に、参照先変数がシリアライズデータに含まれていなければ、参照先の値がセットされます。(’r’は?)

リソース型やクロージャはNG

リソース型やクロージャは標準のserialize()ではシリアライズできません。

シリアライズデータは見れば分かる

シリアライズデータで身近なのは、セッションデータだと思うのですが、一見複雑そうなシリアライズデータでも開いてみると実は結構読めます。何より変数値はほぼそのまま入っているので、なんとなくでも内容を掴むことができます。

PHPユーザならシリアライズデータを読むことは普通だと思うのですが、初日ということでBasicなネタにしてみました。

では、明日のikeekiさん、よろしくお願いします!

PHP unserialize()が__destruct()を実行する?

この記事の所要時間: 328

CakePHPのセキュリティホール(まだの方はご対応を!)から、unserialize()が話題になっています。

このセキュリティホールは、外部から送信された値をチェックせずにunserialize()したことが引き金になっており、安全でない値をunserialize()することの危険性が指摘されています。

下記エントリでは、コードを交えてunserialize()から__destruct()が実行される過程が解説されています。

PHP5 __destruct() and unserialize() function – TokuLog 改メ tokuhirom’s blog

念のための補足なのですが、unserialize()から__destruct()が呼ばれるわけではありません。

下記コードは、PHP5.3.3で実行しています。

unserialize()から実行される関数

unserialize()から実行される関数(メソッド)は以下です。

__autoload、spl_autoload*などのオートローダー

デシリアライズするインスタンスのクラス定義を探す時に実行される可能性があります。

unserialize_callback_funcで設定した関数

上記オートローダー実行してもデシリアライズするインスタンスのクラス定義が存在しない場合に実行されます。ini_set()等で設定していなければ実行されません。

__wakeup

デシリアライズしたインスタンスに__wakeupメソッドが定義されていれば実行されます。

unserialize()から間接的に実行される関数

デシリアライズしたインスタンスの操作によって、結果実行される可能性があるのは以下です。

__destruct()

デシリアライズしたインスタンスの参照が0になったタイミングで実行されます。通常必ず実行されます。

__toString() / __set() / __get() / __call() / __invoke()などのマジックメソッド

デシリアライズしたインスタンスへの操作によって実行される可能性があります。

この中で実行されそうなのは__toString()です。unserialize()した値が文字列だと想定して以下のようなコードを書いていると__toString()が実行されます。

func start
Foo::__toString
func end

unserialize()で__destruct()が実行される?

上記でも触れたように__destruct()は、unserialize()で呼ばれるわけではなく、デシリアライズしたインスタンスの参照が0になるタイミングで実行されます。

これは通常のクラスインスタンスと同じ挙動です。

下記コードを実行してみるとその挙動が確認できます。

実行結果

% php unserialize.php
func start
func end
Foo::__destruct <--- "func end"の後

ただ以下のようにunserialize()の戻り値を変数に格納しない場合は、デシリアライズしたインスタンスへの参照がありませんので、即時に__destruct()が実行されます。

func start
Foo::__destruct   // unserialize()して、即__destruct()が呼ばれる
func end

[おまけ] protected/privateな変数もデシリアライズ可能

ちなみにunserialize()では、protected/privateなインスタンス変数もデシリアライズ可能です。インスタンス変数をprotected/privateにしたところで、unserialize()で汚染される可能性があることには変わりありません。

object(Foo)#2 (3) {
  ["var1"]=>
  string(6) "public"
  ["var2":protected]=>
  string(9) "protected"
  ["var3":"Foo":private]=>
  string(7) "private"
}

でも結果としては実行される

unserialize()が__destruct()を直接実行するわけではないですが、デシリアライズしたインスタンスはどこかで破棄されるので、結果として__destruct()が実行されることには変わりありません。

ただやみくもに「unserialize()が__destruct()を実行する」と考えると問題を見誤る可能性があるのでご注意を。

参考リンク

CakePHPのSecurityComponentに深刻なセキュリティホールが見つかりました

この記事の所要時間: 29

すでにご存知の方も多いと思うのですが、CakePHPに深刻なセキュリティホールが見つかりました。

SecurityComponentの実装に問題があり、結果、外部から任意のコードを実行させることができるという深刻な内容です。

セキュリティホールの概要や攻撃手順については以下のエントリが詳しいですので、ご一読を。
CakePHP の PHP コード実行の脆弱性を使って CakePHP を焦がす

なお、今回の問題はSecurityComponentを利用していない場合は発生しません。

もしSecurityComponentを利用している場合は、以下のいずれかの方法で早急に対策してください。

1. CakePHP1.2.9 or 1.3.6にアップグレードする。

この脆弱性を受けて修正バージョンが出ています。

CakePHP 1.3.6 and 1.2.9 released | The Bakery, Everything CakePHP

2. SecurityComponentを自分で修正する

バージョン変更が容易で無い場合は、SecurityComponent を修正します。

以下に修正差分があるので、このコードをSecurityComponentに適用してください。

https://github.com/cakephp/cakephp/commit/e431e86

3. SecurityComponentの利用をやめる

SecurityComponentを CSRF 対策で利用している人も多いと思いますが、現在のSecurityComponent は必要以上に複雑な実装となっていて内容が掴みづらいという印象です。

いっそのこと自分に必要なシンプルなものを自作してしまうのもひとつの方法です。(私も社内で開発したものを使っています。)

まずは確認を

CakePHPを使っている方は、まずはSecurityComponentを利用しているか確認を。

簡易的ですが、SecurityComponent を使っているかどうかは以下のコマンドでも探せます。

% find app/ -name "*.php" | xargs grep "'Security'"
% find plugin/ -name "*.php" | xargs grep "'Security'"

まだ実際のサイトでの攻撃例は聞かないですが、今後発生する可能性があります。お気をつけを。

PHPで認証して、mod_xsendfileでファイルを出力する

この記事の所要時間: 545

ApacheでX-Sendfileが利用できるmod_xsendfileをPHPと連携して使ってみました。

PHPで認証してから、許可したユーザのみにファイルを出力する、という処理を実装する場合、ファイルはdocument_root外に配置しておいて、readfile()やfpassthru()でファイルを出力するという手法を良く使います。

この方法でも問題無い場合が多いのですが、容量の大きいファイルを出力する際は思ったようなスピードが出ない時があります。

そのような時はmod_xsendfileを使って、ファイル出力の部分をApacheに任せてしまう方法が有効です。

ここでは2010/11/12時点の最新版であるmod_xsendfile 0.12を対象としています。またインストール環境はRHEL、CentOSを想定しています。

mod_xsendfileのインストール

mod_xsendfileはApache2/2.2で動作するモジュールです。

インストールにあたって、apxsコマンドが必要となるので、もしインストールしていない場合はyum等でインストールします。(apxsは、RPMならhttpd-develパッケージに含まれています)

% sudo yum install httpd-devel

次にmod_xsendfileをダウンロードします。mod_xsendfileは、mod_xsendfile.cという1ファイルだけなので、それをダウンロードしてインストールします。

ブラウザからダウンロードする際は問題無いのですが、wgetでダウンロードしようとすると証明書エラーが発生します。–no-check-certificateオプションを付けるとこのエラーを避けることができます。

% wget --no-check-certificate https://tn123.org/mod_xsendfile/mod_xsendfile.c

apxsでmod_xsendfileをインストールします。

% sudo /usr/sbin/apxs -cia mod_xsendfile.c

インストールと共にhttpd.confにLoadModuleが追加されます。

[/etc/httpd/conf/httpd.conf]

LoadModule xsendfile_module   /usr/lib/httpd/modules/mod_xsendfile.so

mod_xsendfileを設定する

mod_xsendfileを利用するために設定を行います。

httpd.confでXSendFilePathを指定する

まず、XSendFilePathで出力を許可するパスを指定します。mod_xsenfileではdocument_root外のファイルを出力することができるので、誤って意図しないファイルの出力を避けるために出力対象のパスを指定する必要があります。

例えば、出力するファイルは「/path/to/images」以下にあるなら以下のように指定します。

[/etc/httpd/conf/httpd.conf]

XSendFilePath /path/to/images

XSendFilePathは、VirtualHostやDirecortyディレクティブでも指定が可能です。Directoryディレクティブでは実行するPHPファイルのパスを指定できます。例えば、CakePHPで指定するなら以下のようになります。(出力ファイルがapp/data以下にあるとします。)

[/etc/httpd/conf/httpd.conf]


  XSendFilePath /path/to/app/data

XSendFileをonにする

次にXSendFileをonに設定します。これによりX-Sendfileが有効となります。

/etc/httpd/conf*な設定ファイルでも記載できるのですが、アプリ側ファイルの方が都合が良いので、.htaccessに設定を書いておきます。

[/path/to/app/webroot/.htaccess]


    XSendFile on

これで設定は完了です。あとはPHPから出力するファイルを指定します。

XSendFileAllowAboveは削除

なおmod_xsendfile0.9ではXSendFileAllowAboveという設定項目があったのですが、これは0.10で削除されたようです。記載しているとエラーになるのでご注意を。

PHPから出力するファイルを指定

mod_xsendfileと使って、PHPからファイルを出力するにはX-Sendfileヘッダで出力ファイルパスを指定します。

下記のようにreadfile()を記載していた箇所(下から2行目)を、X-Sendfileを出力するheader()に書き換えます。

これでmod_xsendfileからファイルが出力されます。

ちょっと気になったこと

X-Sendfileヘッダは外部に出力される?

X-Sendfileヘッダには出力ファイルのパスを指定するので、外部に出力されるのはあまり好ましいことではありません。mod_xsendfileの処理が有効になっていれば、このヘッダは除去され外部には出力されないようになっています。

0バイトのファイルが出力される

X-Sendfileヘッダで指定したファイルパスが、XSendFilePathで指定したパスにマッチしないと0バイトになるようです。必要であれば、XSendFilePathにファイルパスを追加しましょう。

404が発生する

X-Sendfileヘッダで指定したファイルが存在しない場合は404になります。

PHP以外でも使える?

X-Sendfileヘッダをレスポンスヘッダに出力できれば良いので、PHP以外でも利用できるようです。

Apacheで使えるX-Sendfile

数年前にこんなエントリも書いたりしていたのですが、たしか当時はApacheでの実装は無かったと思います。

なんとなくそのままのイメージでいたので、Lighttpd(nginxにも似た機能があったような。X-Accel-Redirectかな。)いいなあと思ってたら、実は結構前からApacheでもできるようになったんですね。

この認証ロジックはPHP、出力はmod_xsendfileと、それぞれ得意な分野に分けるのは、Unixっぽくて好きです。

PHPerのためのYAPC::Asia2010

この記事の所要時間: 21

YAPC::Asia2010 の発表資料、動画が面白いので、まとめ。

YAPC=Yet Another Perl Conferenceは、その名のとおりPerlのイベントです。PHPで言うならPHPカンファレンスにあたるでしょうか。(違ったらごめんなさい)

Perl のイベントということで特に気にしていなかったのですが、先日行われたYAPC::Asia2010の発表資料を見ると PHPer が見てもかなり面白いです。もちろんPerlならではの発表もあるのですが、言語を問わずWebシステム開発をするなら参考になる内容が多くあります。

Perl だから、という理由だけで避けるのはホントに勿体無いので是非見てみて下さい。

PHPerにオススメな発表

PHPユーザの自分が見て面白かった発表です。リンク下にある一言は自分が面白いと思った点で、要約では無いです。内容は各発表を見てみて下さい。

来年は

PPTやKeynoteなどいわゆるプレゼンツールを使っていない発表が多いのも特徴的ですね。

こうしてあげてみるとPHPerでも楽しめる発表が多いです。来年は行ってみようかな。

スクリプト言語間における「lexical closure」の違い – PHPの場合

  • 2010-10-09 (土)
  • PHP
この記事の所要時間: 045

via. スクリプト言語間における「lexical closure」の違い、それともプログラムの違い? – karasuyamatenguの日記

PHPも5.3からクロージャがあります。クロージャの指定の仕方によって挙動が異なりますが、PHPで書くと以下のようになります。

ループでiを0から4まで回す
ループブロック内で:
iを埋め込んだlexical variable、’localvar’を定義。
localvarを参照したclosureをリストに追加。
5つのclosureの値をプリント

スクリプト言語間における「lexical closure」の違い、それともプログラムの違い? – karasuyamatenguの日記

各クロージャの$localvarが独立しているパターン。

foo0 foo1 foo2 foo3 foo4

各クロージャで$localvarを共有しているパターン。(use で指定する変数が参照渡しになっている。)

foo4 foo4 foo4 foo4 foo4

ホーム > PHP

検索
フィード
メタ情報

Return to page top