Friday, May 4, 2012

PHP: How to chain method on a newly created object?


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?


Source: Tips4all

3 comments:

  1. No, when you're using the

    new Classname();


    syntax, you can't chain a method call off the instantiation. It's a limitation of PHP'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.

    ReplyDelete
  2. Define a global function like this:

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


    You will then be able to call:

    with(new Foo)->xyz();

    ReplyDelete
  3. 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);

    ReplyDelete