2

Mac OS XLionでMAMP2.0.1を使用してPHP5.3.6を実行しており、Kohana3.1.3.1を使用しています。

標準のKohanaORMモジュールの__set()メソッドと__get()メソッドを独自のメソッドでオーバーライドしようとしています。一部のモデルは、ORMクラスを拡張するクラスを拡張します。

<?php

class ORM_Localization extends ORM
{

    protected static $_language_cache = array();
    protected $_languages = array();

    public function __construct($id = NULL)
    {
        parent::__construct($id);

        // Load languages which are accepted by the client
        $this->_languages = array_keys(Application::languages());
    }

    public function __get($name)
    {
        /* Debugging #1 */ echo 'GET'.$name;
        /* Debugging #2 */ // exit;
        return $this->localization($name);
    }

    public function __set($name, $value)
    {
        /* Debugging #3 */ var_dump($this->_table_columns);
        /* Debugging #4 */ echo 'SET::'.$name;
        /* Debugging #5 */ // exit;
        $this->localization($name, $value);
    }

    public function localization($name, $value = NULL)
    {
        if (!array_key_exists($name, $this->_table_columns)) {
            // Load avaiable languages from database if not already done
            if (empty(ORM_Localization::$_language_cache)) {
                ORM_Localization::$_language_cache = ORM::factory('languages')
                    ->find_all()
                    ->as_array('id', 'identifier');
            }

            $languages = array();

            // Find the IDs of the languages from the database which match the given language
            foreach ($this->languages as $language) {
                $parts = explode('-', $language);

                do {
                    $identifier = implode('-', $parts);

                    if ($id = array_search($identifier, ORM_Localization::$_language_cache)) {
                        $languages[] = $id;
                    }

                    array_pop($parts);
                } while($parts);
            }

            // Find localization
            foreach ($languages as $language) {
                $localization = $this->localizations->where('language_id', '=', $language)->find();

                try {
                    if ($value === NULL) {
                        return $localization->$name;
                    } else {
                        $localization->$name = $value;
                    }
                } catch (Kohana_Exception $exception) {}
            }
        }

        if ($value === NULL) {
            return parent::__get($name);
        } else {
            parent::__set($name, $value);
        }
    }

}

しかし、PHP 5.3.6では、次のエラーメッセージが表示されます。

例外[0]:Model_Hotel :: __construct()を実行できませんでした

Model_Hotelはこのクラスを拡張し、独自の構成を持っていません。これは、標準のコハナORMモデルであるModel_Hotelのコードです:http://pastie.org/private/vuyig90phwqr9f34crwg

PHP 5.2.17で、私は別のものを手に入れます:

ErrorException [警告]:array_key_exists()[function.array-key-exists]:2番目の引数は配列またはオブジェクトのいずれかである必要があります

コハナでは、クラスを拡張するモデルは、ormモジュールコードのどこかでmysql_fetch_object()によって呼び出されます。

ただし、呼び出されたプロパティを__set()でエコーし、その後終了(#4および#5)すると、「SET :: id」が出力され、エラーメッセージは表示されません。

var_dump()$ this-> _ table_columns(またはこのクラスの他のプロパティ#3)の場合、初期化される前にこのプロパティが持つ値である「NULL」を取得します。$ this-> _ languagesで同じことを繰り返すと、いくつかの言語で埋められるはずの空の配列が得られます。クラスが__constructで初期化されなかったようです。これは、$ this-> _ table_columnsがNULLであり、配列ではないため、PHP5.2.17で発生するエラーを説明しています。

__constructのコメントを解除しても同じエラーが発生します。障害は、localization()メソッドにある必要があります。

私は今数日検索しましたが、何が間違っているのかまったくわかりません。

4

3 に答える 3

3

ORM::__set()呼び出しからキャストデータをロードすることが期待されmysql_fetch_object()ます。この原因のキャスト値を設定できるようにする必要があります。

public function __set($column, $value)
{
    if ( ! isset($this->_object_name))
    {
        // Object not yet constructed, so we're loading data from a database call cast
        $this->_cast_data[$column] = $value;
    }
    else
    {
        // Set the model's column to given value
        $this->localization($column, $value);
    }
}

私もこのソリューションが好きではありませんが、ORM::set()代わりにオーバーライドする必要があります。

于 2011-07-23T17:45:45.243 に答える
1

__construct()オブジェクトの初期化後に自動的に呼び出されます。

$class = new Object;
于 2011-07-23T17:10:19.747 に答える
0

同じ問題が発生したので、この質問についてもう少し情報があります。

1)mysqliおよびmysql_fetch_objectで__set()が__construct()の前に呼び出されることを文書化したPHPバグレポートを見つけました。レポートは2009年のもので、おそらく修正されていますが、私が実行している5.3のバージョンでは、まだ発生しているようです。ここにあります:https ://bugs.php.net/bug.php?id = 48487

2)メソッドの実行中に例外をスローしたり、その他のエラーが発生したりすると、実際の例外/エラーメッセージではなく、__set()このあいまいな「呼び出しできません」というメッセージが表示されます。X::__construct()

私はこうして私の問題を解決することができました:

public function __set($key, $val){
    if($constructor_has_not_run){
        $this->__construct();
    }

    //do stuff
}

私の場合、コンストラクターを問題なく2回実行させることができるので、少し幸運ですが、同じボートに乗っていない可能性があります。

于 2013-04-09T06:46:11.063 に答える