読者です 読者をやめる 読者になる 読者になる

そうそう、とあるファクトリークラス、渡されたパラメータによって該当するクラスのインスタンスを生成するのですが、追加で該当クラスのインスタンスを渡されたらそれ自身を返す処理を入れたら突然動作がおかしくなったのですよ。

<?php

class StateManager
{
    // 特定のステップのステートクラス名
    // getStateにこの定数を渡すとステートオブジェクトを生成可能
    const STATE_FIRST          = 'stItemEntryHalfway';     // 初期ステート
    const STATE_MANAGE         = 'stItemApply';            // 管理に表示する最低のステート
    const STATE_COMPLETION     = 'stManageCompletion';     // 完了済みのステート

    /**
     * ステートオブジェクトのファクトリー
     *
     * @param unknown_type $option
     * @return Model_ItemState_Interface $optionに指定した何かから該当するステートクラスのインスタンスを返す
     */
    public static function getState($option)
    {
        // ステートオブジェクトが渡されたらそのものを返す
        if (is_a($option, 'Model_ItemState_Interface') == true) {
            return $option;
        }

        // データベースの行オブジェクトからステートを取得
        if (is_a($option, 'Zend_Db_Table_Row_Abstract') == true) {
        }

        // ステートのシリアルキーからステートを取得
        if (is_numeric($option) == true) {
        }

        // ステートのクラス名からステートを取得
        if (is_string($option) == true) {
            $st = self::getStateByClassName($option);
            if (!is_null($st)) {
                return $st;
            }
        }

        // 配列からステートを取得
        // 配列の1番目の要素が大分類コード、2番目の要素が中分類コード
        // もしくは、'large'の値が大分類コード、'middle'の値が中分類コード
        if (is_array($option) == true) {
        }

        return null;
    }

どうやらこの is_aという関数、「特定のインターフェイスかクラスのインスタンスをクラス名(or インターフェイス名)と比較」の他に、「特定のインターフェイスかクラスの『クラス名』をクラス名(or インターフェイス名)と比較」という裏機能(?)があるらしく、文字列とクラス名の比較でtrueが「戻ることがある」というすばらしい謎仕様らしいデス。
引数の型が特定できない中での判定なので、$optionを型キャストしてしのぐ事も出来ないしどうすんだという‥‥
(クラス定数やクラス変数の宣言ではオブジェクトの生成は出来ません。念のため。)