我想知道是否有办法在 PHP 中新创建的对象上链接方法?
就像是:
class Foo {
public function xyz() { ... return $this; }
}
$my_foo = new Foo()->xyz();
任何人都知道实现这一目标的方法吗?
我想知道是否有办法在 PHP 中新创建的对象上链接方法?
就像是:
class Foo {
public function xyz() { ... return $this; }
}
$my_foo = new Foo()->xyz();
任何人都知道实现这一目标的方法吗?
在 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 的调用,您可以使用方法调用实例化一个类,然后您就可以自由地将其链接起来。
像这样定义一个全局函数:
function with($object){ return $object; }
然后,您将可以致电:
with(new Foo)->xyz();
在 PHP 5.4 中,您可以链接一个新实例化的对象:
http://docs.php.net/manual/en/migration54.new-features.php
对于旧版本的 PHP,您可以使用 Alan Storm 的解决方案。
这个答案已经过时 - 因此想要更正它。
在 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
好吧,这可能是一个老问题,但就像编程中的很多事情一样——最终答案会改变。
关于 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();
希望这可以帮助像我一样遇到问题的人!
如果他们在未来的版本中“解决这个问题”,那将非常有帮助。我真的很欣赏链接的能力(尤其是在填充集合时):
我在我的框架的基类中添加了一个名为 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);
只是为了完整性(并且为了它的乐趣......),因为似乎没有人提到使用最短(和最不复杂)代码的解决方案。
对于经常使用的短期对象,特别是在编写测试用例时,您通常会创建大量对象,您可能希望优化打字方便(而不是纯度),并结合 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();
笔记: