我想知道是否有办法在PHP中新创建的对象上链接方法?
类似的东西:
class Foo {
public function xyz() { ... return $this; }
}
$my_foo = new Foo()->xyz();
任何人都知道如何实现这一目标?
答案 0 :(得分:97)
在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的调用,您可以使用方法调用实例化一个类,然后您可以自由地链接该类。
答案 1 :(得分:23)
定义这样的全局函数:
function with($object){ return $object; }
然后您就可以致电:
with(new Foo)->xyz();
答案 2 :(得分:11)
在PHP 5.4中,您可以链接一个新实例化的对象:
http://docs.php.net/manual/en/migration54.new-features.php
对于旧版本的PHP,您可以使用Alan Storm的解决方案。
答案 3 :(得分:6)
这个答案已经过时 - 因此想要纠正它。
在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
答案 4 :(得分:3)
嗯,这可能是一个老问题,但与编程中的很多事情一样 - 最终答案会改变。
关于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();
希望这有助于有人像我一样绊倒这个问题!
答案 5 :(得分:1)
如果他们在将来的版本中“修复此问题”,那将非常有用。我非常欣赏链接的能力(特别是在填充集合时):
我在我的框架的基类中添加了一个方法,名为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;
}
}
}
...
}
类::创建() - &GT; SETNAME( '克里斯') - &GT; SetAge(36);
答案 6 :(得分:0)
只是为了完整性(以及它的乐趣......),因为似乎没有人用最短(也是最复杂的)代码提到解决方案。
对于经常使用的短期对象,特别是在编写测试用例时,通常会创建大量对象,您可能希望优化键入方便性(而不是纯度),并且可以组合Alan Storm的{{1}工厂方法和Kenaniah的Foo::instantiate()
全局函数技术。
只需将工厂方法设为全局函数,其名称与类名相同! 。 ; -o(将其作为方便包装器添加到适当的静态with()
周围,或者在没有人看的时候将其移出那里。)
Foo::instantiate()
注: