PHP中的“内联”类实例化? (为了方便链接)

时间:2008-10-10 02:57:58

标签: php oop static-methods

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类“inline “(如上面的代码所示)为此目的?

如果我决定使用静态方法,那么让类的静态方法返回类本身的实例化是不是太可笑了? (有效地编写我自己的构造函数 - 那不是构造函数吗?)感觉有点脏,但如果没有太多可怕的副作用,我可能会这么做。

我想我也可以使用get_user()方法预先实例化UserFactory,但我很好奇我上面提到的解决方案。

6 个答案:

答案 0 :(得分:12)

所有这些提议的解决方案都会使您的代码变得复杂,以便使PHP能够完成一些语法准确性。希望PHP成为一种不那么好的东西(好的)就是通向疯狂的道路。

我会用:

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

很明显,相对简洁,不会引入错误的黑魔法

当然,你总是可以转向Ruby或Python。它会改变你的生活。

  • 是的,我对PHP很苛刻。我每天都使用它。多年来一直在使用它。现实情况是,它已经增加,而不是被设计并显示出来。

答案 1 :(得分: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);
?>

答案 2 :(得分:5)

你能得到类似东西的唯一方法是使用工厂或单例静态方法。例如:

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

使用PHP5反射API创建一个新实例(使用发送到:: instance()的任何args)并返回它,允许你进行链接:

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

顺便说一下,代码足够灵活,在复制静态方法时你唯一需要改变的是PHPDoc注释的@return。


如果您想像我们的朋友Nelson那样过早地优化您的代码,您可以将User :: instance()的内容替换为:

return new self();

答案 3 :(得分:5)

没有理由将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');

答案 4 :(得分:3)

的简单快捷方式
$Obj = new ClassName();
$result = $Obj->memberFunction();

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

答案 5 :(得分:1)

<?php 
//PHP 5.4+ class member access on instantiation support.
$s = (new User())->login()->get_db_data()->get_session_data();