代码之家  ›  专栏  ›  技术社区  ›  aefxx

如何在新创建的对象上链接方法?

  •  54
  • aefxx  · 技术社区  · 16 年前

    class Foo {
        public function xyz() { ... return $this; }
    }
    
    $my_foo = new Foo()->xyz();
    

    7 回复  |  直到 12 年前
        1
  •  102
  •   Alana Storm    12 年前

    在PHP5.4+中,对解析器进行了修改,因此您可以这样做

    (new Foo())->xyz();
    

    将实例化用括号括起来,然后链开。

    在PHP5.4之前,当您使用

    new Classname();
    

    我见过的一种解决这个问题的方法是某种静态实例化方法。

    class Foo
    {
        public function xyz()
        {
            echo "Called","\n";
            return $this;
        }
    
        static public function instantiate()
        {
            return new self();
        }
    }
    
    
    $a = Foo::instantiate()->xyz();
    

        2
  •  23
  •   Kenaniah    15 年前

    定义如下所示的全局函数:

    function with($object){ return $object; }
    

    with(new Foo)->xyz();
    
        3
  •  11
  •   Jackson    14 年前

    在PHP 5.4中,可以将新实例化的对象链接起来:

    http://docs.php.net/manual/en/migration54.new-features.php

    对于旧版本的PHP,可以使用Alan Storm的解决方案。

        4
  •  6
  •   Ingwie Phoenix    12 年前

    这个答案已经过时了,所以我想纠正它。

    <?php class a {
        public function __construct() { echo "Constructed\n"; }
        public function foo() { echo "Foobar'd!\n"; }
    }
    

    现在,我们可以使用这个: $b = (new a())->foo();

    输出为:

    Constructed
    Foobar'd!
    

    更多信息可在手册中找到: http://www.php.net/manual/en/migration54.new-features.php

        5
  •  3
  •   Lukey    13 年前

    abstract class Foo 
    {    
        public static function create() 
        {
            return new static;
        }
    }
    
    class Bar extends Foo
    {
        public function chain1()
        {
            return $this;
        }
    
        public function chain2()
        {
            return $this;
        }
    }
    
    $bar = Bar::create()->chain1()->chain2();
    

    这将很好地工作,并将返回一个新的Bar()实例。

    但是,在PHP 5.4中,您可以简单地执行以下操作:

    $bar = (new Bar)->chain1()->chain2();
    

    希望这能帮助像我一样在这个问题上结结巴巴的人!

        6
  •  1
  •   Kris    15 年前

    我在我的框架的基类中添加了一个名为create()的方法,该方法可以链接到。应自动处理所有子类。

    class baseClass
    {
        ...
        public final static function create()
        {
            $class = new \ReflectionClass(get_called_class());
            return $class->newInstance(func_get_args());
        }
        ...
        public function __call($method, $args)
        {
            $matches = array();
            if (preg_match('/^(?:Add|Set)(?<prop>.+)/', $method, $matches) > 0)
            {
                //  Magic chaining method
                if (property_exists($this, $matches['prop']) && count($args) > 0)
                {
                    $this->$matches['prop'] = $args[0];
                    return $this;
                }
            }
        }
        ...
    }
    

        7
  •  0
  •   Sz.    11 年前

    只是为了完整性(为了好玩…),因为似乎没有人提到过使用最短(最不复杂)代码的解决方案。

    Foo::instantiate() 工厂法和基纳尼雅法 with() 全局函数技术。

    简单地将工厂方法作为 全局函数 . ;-o(或者将其添加为适当的静态 Foo::实例化()

    class Foo
    {
        public function xyz()
        {
            echo "Called","\n";
            return $this;
        }
    }
    
    function Foo()
    {
        return new Foo();
    }
    
    $a = Foo()->xyz();
    

    注:

    • 我不会在生产代码上这样做。虽然有点“性感”,但这是对基本编码原则的滥用(如“最小惊喜原则”(虽然这实际上是相当直观的语法)或“不要重复你自己”,特别是如果用一些参数包装一个真正的工厂方法,顺便说一句,这本身已经是对DRY的滥用…),另外,PHP在未来可能会改变,以有趣的方式破坏这样的代码。