1

インスタンス化された静的コンテキストで呼び出すことができるいくつかのPHPメソッドをセットアップしようとしています。これを行うためのいくつかの良い方法は何ですか?たとえば、私は次のことができるようにしたいと思います。

Foo::bar($item); 
foo($item)->bar();

2つの別々のクラスを設定し、各関数でthisArgを変更して他の関数に委任することもできますが、もっと良い方法が必要なようです。1つのクラスだけでそれを行うことを考えることができる唯一の方法は、次のようなものです。

function foo($item = null) {
    return $item instanceof Foo ? $item : new Foo($item);
}

class Foo { 
    protected $wrapped;

    public function __construct($item = null) { 
        $this->wrapped = $item;
    }

    public function get() {
        return $this->wrapped;
    }

    public function bar($item = null) {
        isset($this) and $item = &$this->wrapped;
        // do stuff with $item
        return isset($this) ? $this : $item;
    }
}

underscore.phpのコードを見ると、彼らはそのようなことをしています。コンテキストを決定するために使用すると警告が発生する可能性があることを指摘するいくつかの関連する質問をしばらく前に読んだことisset($this)がありますが、それはうまくいくようです...それに関する更新された考えはありますか?もう1つの可能性は、2つのクラスを作成することです。1つはすべて静的バージョンのメソッドを使用し、もう1つは__callを使用して次のような静的メソッドに委任します。

class _Foo
{
        protected $wrapped;

        public function __construct($item = null) { 
            $this->wrapped = $item;
        }

        public function __call($method_name, $args) { 
            array_unshift($args, $this->wrapped);
            $this->wrapped = call_user_func_array('Foo::' . $method_name, $args);
            return $this;
        }


}

アイデア?

4

2 に答える 2

2

http://www.php.net/manual/en/domdocument.loadxml.phpはこれを行いますが、静的コンテキストから呼び出されると、E_STRICT.

大まかに言えば、静的でインスタンスの呼び出し可能なメソッドを作成することは今のところ機能しますが、その機能は削除される可能性があります。おそらく、必要なことを達成する別の方法がありますか?

編集: をスローせずに言及したように、機能は __call でシミュレートできますがE_STRICT、2 つのクラスは必要ありません。

<? //PHP 5.4+
class mightBeInstance
{
    public function __call($name, $arguments)
    {
        if ($name === 'doSomething') {
            return static::doSomething($this);
        }
    }

    public static function doSomething(mightBeInstance $item = null)
    {
        if ($item === null) {
            $item = new static();
        }

        $item->didSomething = true; // Or whatnot

        return $item;
    }
}

var_dump(
    (new mightBeInstance)->doSomething(),
    mightBeInstance::doSomething()
);

?>
于 2012-05-04T05:04:52.443 に答える
0

これが唯一の信頼できるソリューションです。5.3+ で動作しますが (下部のインライン オブジェクトのインスタンス化を除く)、やや扱いにくいです。

class foo {
    protected function __call($method, $args) {
        if ($method == 'bar') {
            return $this->bar($args[0]);
        }
    }
    protected function bar($baz) {
        return "object context: $baz\n";
    }

    public static function __callStatic($method, $args) {
        if ($method == 'bar') {
            return self::barStatic($args[0]);
        }
    }
    protected static function barStatic($baz) {
        return "static context: $baz\n";
    }
}

echo foo::bar('baz');
echo (new foo())->bar('baz');

非推奨:E_DEPRECATED以下は PHP 5.6 では機能しますが、PHP 7.0 で実行すると、「非静的メソッド foo::bar() を静的に呼び出すべきではありません」というメッセージとともにエラーがスローされます。問題はisset($this)、あなたが言うようにではなく、単一の関数に二重の義務を負わせることにあります。それは静的であるか、そうでないかのどちらかです。PHP 7.0 でもサポートされていますが、これに頼るべきではありません。

class foo {
    public function bar($baz) {
        if (isset($this)) {
            return "object context: $baz\n";
        } else {
            return "static context: $baz\n";
        }
    }
}

echo foo::bar('baz');
echo (new foo())->bar('baz');

動作しません:これにより、PHP 5.6 と PHP 7.0 の両方で「Cannot redeclare foo::bar()」という致命的なエラーがスローされますが、代わりにこの方法で実行できれば理想的です。

class foo {
    public function bar($baz) {
        return "object context: $baz\n";
    }
    public static function bar($baz) {
        return "static context: $baz\n";
    }
}

echo foo::bar('baz');
echo (new foo())->bar('baz');

おそらく将来のバージョンでは、非推奨の使用法が削除されたら、それができるようになるでしょう。

于 2015-10-01T02:52:46.793 に答える