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

发布于 2024-08-20 05:22:39 字数 191 浏览 8 评论 0原文

我想知道是否有办法在 PHP 中新创建的对象上链接方法?

比如:

class Foo {
    public function xyz() { ... return $this; }
}

$my_foo = new Foo()->xyz();

有人知道实现这一目标的方法吗?

I would like to know whether there's a way to chain methods on a newly created object in PHP?

Something like:

class Foo {
    public function xyz() { ... return $this; }
}

$my_foo = new Foo()->xyz();

Anyone know of a way to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

蝶…霜飞 2024-08-27 05:22:39

在 PHP 5.4+ 中,解析器已被修改,因此您可以执行类似以下操作:

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

将实例化放在括号中,然后链接起来。

在 PHP 5.4 之前,当您使用语法时

new Classname();

,无法将方法调用链接到实例化。这是 PHP 5.3 语法的限制。一旦对象被实例化,您就可以将其链接起来。

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

class Foo
{
    public function xyz()
    {
        echo "Called","\n";
        return $this;
    }

    static public function instantiate()
    {
        return new self();
    }
}


$a = Foo::instantiate()->xyz();

通过将对 new 的调用包装在静态方法中,您可以使用方法调用实例化一个类,然后您可以自由地将其链接起来。

In PHP 5.4+, the parser's been modified so you can do something like this

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

Wrap the instantiation in parenthesis, and chain away.

Prior to PHP 5.4, when you're using the

new Classname();

syntax, you can't chain a method call off the instantiation. It's a limitation of PHP 5.3's syntax. Once an object is instantiated, you can chain away.

One method I've seen used to get around this is a static instantiation method of some kind.

class Foo
{
    public function xyz()
    {
        echo "Called","\n";
        return $this;
    }

    static public function instantiate()
    {
        return new self();
    }
}


$a = Foo::instantiate()->xyz();

By wrapping the call to new in a static method, you can instantiate a class with method call, and you're then free to chain off that.

夜血缘 2024-08-27 05:22:39

像这样定义一个全局函数:

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

然后您将能够调用:

with(new Foo)->xyz();

Define a global function like this:

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

You will then be able to call:

with(new Foo)->xyz();
北方的韩爷 2024-08-27 05:22:39

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

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

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

In PHP 5.4 you can chain off a newly instantiated object:

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

For older versions of PHP, you can use Alan Storm's solution.

与酒说心事 2024-08-27 05:22:39

这个答案已经过时了 - 因此想纠正它。

在 PHP 5.4.x 中,您可以将方法链接到新调用。让我们以这个类为例:

<?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

This answer is outdated - therefore want to correct it.

In PHP 5.4.x you can chain a method to a new-call. Let's take this class as example:

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

Now, we can use this: $b = (new a())->foo();

And the output is:

Constructed
Foobar'd!

Further information may be found on the manual: http://www.php.net/manual/en/migration54.new-features.php

影子是时光的心 2024-08-27 05:22:39

嗯,这可能是一个老问题,但就像编程中的很多事情一样 - 最终答案会改变。

关于 PHP 5.3,不,您不能直接从构造函数链接。然而,要扩展已接受的答案,为了正确适应继承,您可以这样做:

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

希望这可以帮助像我一样遇到这个问题的人!

Well, this may be an old question but as with a lot of things in programming - eventually the answer changes.

Regarding PHP 5.3, no, you can't chain directly from the constructor. To expand on the accepted answer however, in order to properly accommodate for inheritance, you can do:

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

That will work just fine and will return you a new Bar() instance.

In PHP 5.4, however, you can simply do:

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

Hopefully this helps someone stumbling across the question like I have!

掀纱窥君容 2024-08-27 05:22:39

如果他们在未来的版本中“修复这个问题”,那将会非常有帮助。我真的很欣赏链接的能力(特别是在填充集合时):

我在框架的基类中添加了一个名为 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;
            }
        }
    }
    ...
}

类::create()->SetName('Kris')->SetAge(36);

It would be really helpful if they 'fix this' in a future release. I really appreciate the ability to chain (especially when populating collections):

I added a method to the base class of my framework called create() that can be chained off of. Should work with all descendant classes automatically.

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;
            }
        }
    }
    ...
}

Class::create()->SetName('Kris')->SetAge(36);

财迷小姐 2024-08-27 05:22:39

只是为了完整性(并且为了它的乐趣......),因为似乎没有人提到具有最短(且最不复杂)代码的解决方案。

对于经常使用的短期对象,特别是在编写测​​试用例时,您通常会创建大量对象,您可能需要优化输入便利性(而不是纯粹性),并结合 Alan Storm 的 Foo::instantiate () 工厂方法和 Kenaniah 的 with() 全局函数技术。

只需将工厂方法设置为与类同名的全局函数即可!。 ;-o (将其添加为适当的静态 Foo::instantiate() 周围的便捷包装器,或者只是在没有人在看的时候将其移到那里。)

class Foo
{
    public function xyz()
    {
        echo "Called","\n";
        return $this;
    }
}

function Foo()
{
    return new Foo();
}

$a = Foo()->xyz();

注意:

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

Just for the sake of completeness (and for the fun of it...), since nobody seems to have mentioned the solution with the shortest (and least sophisticated) code.

For frequently used short-lived objects, especially when writing test cases, where you typically do lots of object creation, you may want to optimize for typing convenience (rather than purity), and sorta' combine Alan Storm's Foo::instantiate() factory method and Kenaniah's with() global function technique.

Simply make the factory method a global function with the same name as the class!. ;-o (Either add it as a convenience wrapper around the proper static Foo::instantiate() or just move it out there while nobody is looking.)

class Foo
{
    public function xyz()
    {
        echo "Called","\n";
        return $this;
    }
}

function Foo()
{
    return new Foo();
}

$a = Foo()->xyz();

NOTE:

  • I WOULDN'T DO THIS on production code. While kinda' sexy, this is an abuse on basic coding principles (like "principle of least surprise" (although this is actually rather intuitive syntax), or "don't repeat yourself", esp. if wrapping a real factory method with some parameters, which itself, BTW, is already an abuse of DRY...), plus PHP may change in he future to break code like this in funny ways.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文