is_subclass_ofを使う場面

is_subclass_ofというメソッドを見つけました。機能は、指定したクラスを継承しているかを判定してくれるというものです。

instanceofやis_aメソッドを使った判定と同じイメージです。違いはinstanceofやis_aがオブェジェクトだけを判定できるのに対して、is_subclass_ofはクラス名について判定することができます。

クラスからオブジェクトを生成する前に判定が可能ということです。

複数のプログラマが利用する共通部を作成するような場合に使えそうです。今回は、あるディレクトリ配下のクラスファイルを全て読み込んで、特定のクラスを継承しているクラスのみ生成するという処理に利用しました。

誤ったファイルを置かれても、不具合が出ないための対応ですが、ちゃんと作れとか、ルールが明記してあるドキュメントを整備しろとかあるとは思いますが、これはこれでいい対策かなと思います。

php5.4からはerror_reportingのE_ALLにE_RISTRICTが含まれる

error_reportingは、php.iniの中に書かれている設定で、どのレベルのエラーを出力するかの設定です。このE_STRICTのエラーは、php5でphp4の書式で記述されているプログラムを実行すると、大量に出ます。static定義されていないメソッドを、クラス名::メソッド名で呼んだりしたときに出るのです。

E_ALLは、全部のエラーを出力してねっていう設定です。
これまでは、”E_ALL & ~E_NOTICE”とかでNOTICEメッセージを抑止している方もいたと思います。このE_ALLのなかに、E_STRICTで表示されるメッセージは含まれていなかったのです。今まで。それが、php5.4からは、E_ALLに含まれることになりました。

php5.4に上げた途端エラーメッセージが大量に!って場面に遭遇するのです。
PAER使っている方は、必ず遭遇するのではないでしょうか。php4でも動作するように作られているので。

E_STRICTのエラーを表示しないためには、以下のように記述します。

error_reporting = E_ALL & ~E_STRICT

php.iniのコメントでも親切に例がのってました。

; Common Values:
;   E_ALL (Show all errors, warnings and notices including coding standards.)
;   E_ALL & ~E_NOTICE  (Show all errors, except for notices)
;   E_ALL & ~E_NOTICE & ~E_STRICT  (Show all errors, except for notices and coding standards warnings.)
;   E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR  (Show only errors)
; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED  <= こことか
; Development Value: E_ALL
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT           <= こことか
; http://php.net/error-reporting
; error_reporting = E_ALL | E_STRICT
error_reporting = E_ALL & ~E_STRICT & ~E_DEPRECATED

php4から持ってきたプログラムがうまく動かないと聞かれて調べてたんですが、勉強になりました。
以下のサイトを参考にさせて頂き、大変ありがたかったです。

http://developer.cybozu.co.jp/tech/?p=982
http://vivit-jc.hatenablog.com/entry/2013/02/12/210950
http://blog.gufii.net/weblog/archives/19

phpの連想配列から指定したキーの要素を、指定したキーの順番で取得する方法

日本語で説明すると面倒ですねw

以下のような配列から

$list = array(
    "item100" => "aaa", 
    "item50" => "bbb", 
    "item30" => "ccc", 
    "item10" => "ddd"
);

以下のような配列を取得したかったのです。

$list = array(
    "item30" => "ccc", 
    "item50" => "bbb"
);

最終的にたどり着いたのは、この方法でした。

$list = array(
    "item100" => "aaa", 
    "item50" => "bbb", 
    "item30" => "ccc", 
    "item10" => "ddd"
);
$cols = array("item30", "item50");
$ret = array_merge(
    array_flip($cols), 
    array_intersect_key($list, array_flip($cols))
);

array_intersect_keyを行うと必要な要素は取得できるんですが、要素の並び順がもともとの $list の状態を保持していました。そこで、array_mergeを使って、指定したkeyの順番を保ちつつ、値を $list のもので上書きしています。

trigger_errorの使い方

使い方マニュアルはこちら。
http://phpspot.net/php/man/php/function.trigger-error.html

私は読んでもピンとこなかったので、動かしてみることに。
trigger_errorに渡したメッセージが、ブラウザに出力されました。表示形式はphpのエラーと同じフォーマットで、trigger_errorを実行したファイル、ファイルの行数、設定したメッセージが表示されます。
(”}”の対応が間違ってたりしたときに、warningとかでるあのフォーマットです。)

自分で共通クラスとかつくったときに、使い方が間違っていたら今までException発生させて間違っているよということを通知していましたが、trigger_errorを使った方がいいかなと思いました。
Exceptionの中身からエラー発生行数とか見つけなくていいですし。

ZendFramework1.11.1はPCREのUnicode対応が必要

ZendFramework1.10.1から、1.11.1に変えたときに、Noticeメッセージがでました。内容は、「PCREがUnicodeをサポートしてませんよ」というもの。
Niticeメッセージはでないようにしてたのにと思って調べてみたら、ZendFrameworkのZend_Locale内で、trigger_errorを使ってメッセージを出してました。なので、ちゃんとPCREをUnicode対応にしました。

参考にさせていただいたサイトは以下です。
http://junrei.dip.jp/wordpress/nagios/pnp4nagios%EF%BC%880-6-2%EF%BC%89%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/

以下のコマンドで、PCREがUnicodeに対応してないことを確認。

# pcretest -C
PCRE version 8.02 2010-03-19
Compiled with
  UTF-8 support
  No Unicode properties support
  Newline sequence is LF
  \R matches all Unicode newlines
  Internal link size = 2
  POSIX malloc threshold = 10
  Default match limit = 10000000
  Default recursion depth limit = 10000000
  Match recursion uses stack

まずは、以下のファイルを作成。
デフォルトのリポジトリに、pcre-unicodeがないので、下記のリポジトリを追加します。私の環境だと、phpをインストールするときに、追加してました。(忘れてました。。)

# vi /etc/yum.repos.d/utterramblings.repo

[utterramblings]
name=Jason's Utter Ramblings Repo
baseurl=http://www.jasonlitka.com/media/EL$releasever/$basearch/
enabled=0
gpgcheck=1
gpgkey=http://www.jasonlitka.com/media/RPM-GPG-KEY-jlitka

そして、以下のコマンドを実行

# yum install pcre-unicode

再度、unicodeに対応しているかをコマンドで確認。

# pcretest -C
PCRE version 8.02 2010-03-19
Compiled with
  UTF-8 support
  Unicode properties support
  Newline sequence is LF
  \R matches all Unicode newlines
  Internal link size = 2
  POSIX malloc threshold = 10
  Default match limit = 10000000
  Default recursion depth limit = 10000000
  Match recursion uses stack

Unicode properties supportになったのでOK。
Noticeメッセージもでなくなりました。
ZendFrameworkを利用するときに覚えておく必要がありそうです。

ZendFrameworkの環境変数APPLICATION_ENVを設定する

ZendFrameworkでは、index.phpにもともと書いてある記述に以下の環境変数に関わるものがあります。

/ Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));

APPLICATION_ENVが設定されてなかったら、’production’ という文字列を、APPLICATION_ENVとして設定するという内容です。このAPPLICATION_ENVはどこで使われているかというと、Bootstrap内で、application.iniを読み込む際に、パラメタとして渡されています。

application.iniは、DB接続設定等を書くファイルで、APPLICATION_ENVの値を、本番環境、テスト環境等で変えることによって、ファイルを編集することなく、DB接続先の設定を環境に合ったものに設定することができます。iniファイルの書き方は、こちらをご参照ください(http://framework.zend.com/manual/1.11/ja/zend.config.adapters.ini.html)

今回、/etc/sysconfig/httpd に以下の記述を追加すると、apacheにて環境変数を追加することができました。

export APPLICATION_ENV="development"

.htaccessを使うと、”setEnv”を使って記述することもできます。その場合の書き方は以下になります。

setEnv APPLICATION_ENV development

これまで、.htaccessを使ったやり方のみでやってきて、/etc/sysconfig/httpd を編集する方法を知りませんでした。

Zend_Mailで文字化けしなくなっていた

以前、こんな記事を書きました。
https://life.co-hey.com/2009/02/zendframework_175_1/

その後、Zend_Mailをいじることはなかったんですが、最近また利用する機会があったのですが、Zend_Mailの中身を修正しなくても、文字化けしなくなっていました。

$e = Zend_Debug::dump($errors->exception, null, false);
$mail = new Zend_Mail('iso-2022-jp');
$mail->addTo('test@co-hey.com')
     ->setFrom('error@co-hey.com')
     ->setSubject(mb_convert_encoding('例外が発生しました', 'iso-2022-jp', 'UTF-8'))
     ->setBodyText(mb_convert_encoding(strip_tags(htmlspecialchars_decode($e)), 'iso-2022-jp', 'UTF-8'))
     ->send();

ErrorController.phpの中で、上記のプログラムでエラー発生箇所をメールするという用途で使っています。バージョンアップの度に、Zend_Mailを1行修正する手間がいらなくなるのはうれしいです。

動作を試したのは、1.10.1ですが、いつから文字化けが解消されていたのかはわかりません。。

VMをつくり直すときに役に立ったサイト

プログラムテスト環境として利用していたVMのハードディスク容量が足りなくなったので、新たに作り直しました。前回は勉強のためとソースからコンパイルして作ったんですが、今回はyumを使った方法を試してみることに。

途中うまく動かない箇所があったんですが、yumリポジトリを変えて再度構築しなおしたら、意図通りに動作する環境ができあがりました。そのときに参考にしたサイトを忘れないようにメモです。

いくつかのサイトを参考にしながら作成しましたが、うまくいったのはこのサイトの方法で構築したときでした。
【VMware Player上のCentOSに開発環境を構築 #2CommentsAdd Star】
http://rewish.org/php_mysql/vm_player_config_2

Gitのインストールの際に参考にしたサイト
【centos5.3でyumを使ってgitをインストールする】
http://d.hatena.ne.jp/uk_oasis/20090807/1249633626

ついでに調べた、Gitのクライアント。
【tortoiseGit】 tortoiseSVNのgit版。Win専用。
http://code.google.com/p/tortoisegit/

【SmartGit】 Win、Mac、Linuxに対応
http://www.syntevo.com/smartgit/index.html
Gitだけじゃなくて、CSV、SVNのクライアントも。慣れたら同じ使い勝手で全部いけるとしたら一番いいのかも。

【Gitti】 Mac専用。画面がいい感じ。
http://www.gittiapp.com/

連想配列の同じkey名の値を加算する

前に覚えた func_get_args というメソッドを使える機会があったので、使った内容をメモ。

タイトルの通り、パラメタで渡された連想配列のうち、同じkey名の値を加算します。パラメタはいくつでも渡せます。 func_get_argsのいいところ。

    //-----------------------------------------------------------------
    // パラメタで渡された配列の、同じkey名の値を合算した配列を返却する
    //-----------------------------------------------------------------
    protected function _arrayAdd()
    {
        $ret = array();

        // パラメタが1つ以上ない場合は処理をしない
        $params = func_get_args();
        if (count($params) == 0 ) { return; }

        foreach ($params as $item) {
            if (!is_array($item)) { continue; }

            foreach ($item as $key => $value) { $ret[$key] += $value; }
        }

        return $ret;
    }

extractという関数を見つけた

wordpressのソースを見ていたら、extractという関数を見つけた。
詳細はこちら。http://php.net/manual/ja/function.extract.php

連想配列の、key名の変数に、vlaueの値をつっこんでくれる関数。
今まで、

list($key1, $key2, $key3) = explode($list);

のように書いてた部分が、

extract($list); 

というようにもかける。

listだと、変数の数を動的に増やしたいときに不便だと感じるときがあったので、そういうときの代替案として使えそう。