代码之家  ›  专栏  ›  技术社区  ›  Max Cantor

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

  •  9
  • Max Cantor  · 技术社区  · 17 年前

    Python和Ruby等面向对象语言中常用的一个习惯用法是实例化一个对象并链接方法,这些方法返回对对象本身的引用,例如:

    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();
    

    这似乎可以使用静态方法来实现,这可能是我最终要做的,但我想检查lazywb: 是否真的有一种干净、简单的方法来“内联”实例化PHP类(如上面的代码片段所示) 为了这个目的?

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

    我想我也可以用get_user()方法预实例化一个UserFactory,但我对我上面问的问题的解决方案很好奇。

    6 回复  |  直到 17 年前
        1
  •  13
  •   Toby Hede    17 年前

    所有这些提出的解决方案都会使您的代码复杂化,以便弯曲PHP来实现一些语法上的精确性。想要PHP成为它不好的东西(比如好的东西)是走向疯狂的道路。

    我只会使用:

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

    它清晰、相对简洁,不涉及 魔法 这可能会引入错误。

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

    • 是的,我对PHP很苛刻。我每天都用它。多年来一直在使用它。事实上,它已经 生长 ,而不是设计出来的。
        2
  •  8
  •   user19302 user19302    17 年前
    <?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);
    ?>
    
        3
  •  6
  •   Victor Nicollet Victor Nicollet    16 年前

    一个简单的快捷方式

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

    $result = (new ClassName())->memberFunction();
    
        4
  •  5
  •   igaster    11 年前

    没有理由把破解(解决语法问题)和对象创建代码本身粘在一起。

    由于新表达式不能用作对象运算符的左成员,但函数调用表达式可以,因此您只需要将对象包装在对返回其自身参数的函数的调用中:

    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');
    
        5
  •  4
  •   dcousineau    17 年前

    获得类似结果的唯一方法是使用工厂或单例静态方法。例如:

    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();
    
        6
  •  1
  •   PHPDave    10 年前
    <?php 
    //PHP 5.4+ class member access on instantiation support.
    $s = (new User())->login()->get_db_data()->get_session_data();
    
    推荐文章