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