天天看点

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

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

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

就像是:

class Foo {

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

}

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

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

7个解决方案

99 votes

在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的调用包装在静态方法中,可以使用方法调用实例化一个类,然后可以自由地将其链接起来。

Alan Storm answered 2019-11-13T01:47:07Z

23 votes

定义这样的全局函数:

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

然后,您将可以致电:

with(new Foo)->xyz();

Kenaniah answered 2019-11-13T01:47:37Z

11 votes

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

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

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

Jackson answered 2019-11-13T01:48:13Z

6 votes

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

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

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]

Ingwie Phoenix answered 2019-11-13T01:49:02Z

3 votes

好吧,这可能是一个古老的问题,但是与编程中的许多事情一样,最终答案也改变了。

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

希望这可以帮助像我一样绊脚石的人!

Lukey answered 2019-11-13T01:49:53Z

1 votes

如果他们在将来的版本中“解决此问题”,那将真的很有帮助。 我非常欣赏链接的能力(尤其是在填充集合时):

我在框架的基类中添加了一个可以链接的方法,称为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)(?.+)/', $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);

Kris answered 2019-11-13T01:50:30Z

0 votes

仅仅为了完整性(为了乐趣),因为似乎没有人提到使用最短(和最不复杂)代码的解决方案。

对于经常使用的短寿命对象,尤其是在编写测试用例时,通常会创建大量对象,因此您可能需要优化其键入便利性(而不是纯粹性),然后将Alan Storm的Foo::instantiate()工厂方法和Kenaniah的with()全局方法结合起来 功能技术。

只需使factory方法成为与类同名的全局函数即可。 ; -o(要么将其添加为适当的静态Foo::instantiate()周围的便利包装,要么在没人看的时候将其移到那里。)

class Foo

{

public function xyz()

{

echo "Called","\n";

return $this;

}

}

function Foo()

{

return new Foo();

}

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

注意:

我不会在生产代码上这样做。 虽然有点性感,但这是对基本编码原理的滥用(例如“最不惊讶的原则”(尽管这实际上是相当直观的语法),或者“不要重复自己”,特别是如果将实际工厂方法与某些方法包装在一起 参数本身就是BTW,已经滥用了DRY ...),而且PHP将来可能会更改,以有趣的方式破坏此类代码。

Sz. answered 2019-11-13T01:51:17Z