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

没有理由将 hack(解决语法问题)和对象创建代码本身结合在一起。

由于 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 回答
6

一个简单的快捷方式

$Obj = new ClassName();
$result = $Obj->memberFunction();

$result = (new ClassName())->memberFunction();
于 2014-03-14T09:04:31.737 回答
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 回答