9

Python や Ruby などの OO 言語で一般的に使用されるイディオムは、オブジェクトをインスタンス化し、オブジェクト自体への参照を返すメソッドをチェーン化することです。

s = User.new.login.get_db_data.get_session_data

PHP では、この動作を次のように再現できます。

$u = new User();
$s = $u->login()->get_db_data()->get_session_data();

以下を試みると、次の結果になりsyntax error, unexpected T_OBJECT_OPERATORます。

$s = new User()->login()->get_db_data()->get_session_data();

これはおそらく私がやることになる静的メソッドを使用して達成できるようですが、lazyweb を確認したかったのですが、PHP クラスを「インライン」でインスタンス化するためのクリーンで簡単な方法は実際にありますか?この目的のために?

静的メソッドを使用することにした場合、クラスの静的メソッドがクラス自体のインスタンス化を返すのはあまりにも魔術的ですか? (コンストラクターではない独自のコンストラクターを効果的に作成しますか?) ちょっと汚い感じがしますが、恐ろしい副作用があまりない場合は、そうするかもしれません。

get_user() メソッドを使用して UserFactory を事前にインスタンス化することもできると思いますが、上記で尋ねたことに対する解決策に興味があります。

4

6 に答える 6

13

これらの提案された解決策はすべて、コードを複雑にして、PHP を曲げて構文上の優れた機能を実現します。PHP をそうでないもの (良いものなど) にしたいというのは、狂気への道です。

私はただ使用します:

$u = new User();
$s = $u->login()->get_db_data()->get_session_data();

明確で比較的簡潔で、エラーを引き起こす可能性のある黒魔術は含まれていません。

もちろん、いつでも Ruby や Python に移行できます。それはあなたの人生を変えるでしょう。

  • そしてええ、私はPHPに厳しいです。毎日使っています。何年も使用しています。現実には、設計されて表示されるのではなく、付加されています。
于 2008-10-10T03:44:55.577 に答える
8
<?php

    class User
    {
        function __construct()
        {
        }

        function Login()
        {
            return $this;
        }

        function GetDbData()
        {
            return $this;
        }

        function GetSession()
        {
            return array("hello" => "world");
        }
    }

    function Create($name)
    {
        return new $name();
    }

    $s = Create("User")->Login()->GetDbData()->GetSession();

    var_dump($s);
?>

これは可能な解決策です:)もちろん、関数にはより適切な名前を選択する必要があります...

または、少しオーバーヘッドを気にしない場合:

<?php

    class User
    {
        function __construct($test)
        {
            echo $test;
        }
...
    }

    function CreateArgs($name)
    {
        $ref = new ReflectionClass($name);
        return $ref->newInstanceArgs(array_slice(func_get_args(), 1));
    }

    $s = CreateArgs("User", "hi")->Login()->GetDbData()->GetSession();

    var_dump($s);
?>
于 2008-10-10T03:27:10.183 に答える
6

ハック (構文の問題を回避するため) とオブジェクト作成コード自体をくっつける理由はありません。

new-expression はオブジェクト演算子の左のメンバーとして使用できませんが、関数呼び出し式は使用できるため、独自の引数を返す関数への呼び出しでオブジェクトをラップするだけで済みます。

function hack($obj) { return $obj; }

$mail = hack(new Zend_Mail())
  -> setBodyText('This is the text of the mail.')
  -> setFrom('somebody@example.com', 'Some Sender')
  -> addTo('somebody_else@example.com', 'Some Recipient')
  -> setSubject('TestSubject');
于 2009-09-15T21:43:16.117 に答える
4

同様のものを取得できる唯一の方法は、ファクトリまたはシングルトン静的メソッドを使用することです。例えば:

class User
{
    //...
    /**
     *
     * @return User
     */
    public static function instance()
    {
        $args = func_get_args();
        $class = new ReflectionClass(__CLASS__);
        return $class->newInstanceArgs($args);
    }
    //...
}

これは、PHP5リフレクションAPIを使用して新しいインスタンスを作成し(:: instance()に送信された引数を使用)、それを返し、チェーンを実行できるようにします。

$s = User::instance()->login()->get_db_data()->get_session_data();

ちなみに、そのコードは十分に柔軟なので、静的メソッドをコピーするときに変更する必要があるのは、PHPDocコメントの@returnだけです。


友人のNelsonのようにコードを時期尚早に最適化したい場合は、User :: instance()の内容を次のように置き換えることができます。

return new self();
于 2008-10-10T03:33:18.613 に答える
1
<?php 
//PHP 5.4+ class member access on instantiation support.
$s = (new User())->login()->get_db_data()->get_session_data();
于 2015-07-27T20:41:38.610 に答える