Как привязать метод к вновь созданному объекту?


Я хотел бы знать, есть ли способ связать методы для вновь созданного объекта в PHP?

Что-то вроде:

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

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

Кто-нибудь знает способ добиться этого?

Author: user2864740, 2010-02-03

7 answers

В 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 в статический метод, вы можете создать экземпляр класса с помощью вызова метода, а затем вы можете отключить его.

 95
Author: Alan Storm, 2014-09-09 14:29:26

Определите глобальную функцию следующим образом:

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

Затем вы сможете позвонить:

with(new Foo)->xyz();
 23
Author: Kenaniah, 2011-07-12 18:32:15

В PHP 5.4 вы можете создать цепочку из вновь созданного объекта:

Http://docs.php.net/manual/en/migration54.new-features.php

Для более старых версий PHP вы можете использовать решение Алана Шторма.

 11
Author: Jackson, 2012-06-10 16:42:35

Этот ответ устарел - поэтому я хочу его исправить.

В 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

 5
Author: Ingwie Phoenix, 2013-10-26 22:40:18

Ну, это может быть старый вопрос, но, как и во многих других вещах в программировании, в конечном итоге ответ меняется.

Что касается 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();

Надеюсь, это кому-то поможет натыкаюсь на такой вопрос, как у меня!

 2
Author: Lukey, 2013-04-30 09:23:57

Было бы действительно полезно, если бы они "исправили это" в будущем выпуске. Я действительно ценю возможность объединения в цепочку (особенно при заполнении коллекций):

Я добавил метод в базовый класс своей платформы под названием 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;
            }
        }
    }
    ...
}

Класс::создать()->Имя набора ('Kris')->Настройка(36);

 1
Author: Kris, 2011-02-14 06:58:31

Просто для полноты картины (и для удовольствия...), поскольку никто, похоже, не упомянул решение с самым коротким (и наименее сложным) кодом.

Для часто используемых недолговечных объектов, особенно при написании тестовых примеров, когда вы обычно создаете много объектов, вы можете оптимизировать их для удобства ввода (а не для чистоты) и, как бы, объединить фабричный метод Алана Шторма Foo::instantiate() и метод глобальных функций Кенании with().

Просто сделайте фабричный метод глобальной функцией с тем же именем, что и класс!. ;- o (Либо добавьте его в качестве удобной оболочки вокруг соответствующего статического Foo::instantiate(), либо просто переместите его туда, пока никто не смотрит.)

class Foo
{
    public function xyz()
    {
        echo "Called","\n";
        return $this;
    }
}

function Foo()
{
    return new Foo();
}

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

ПРИМЕЧАНИЕ:

  • Я БЫ НЕ СТАЛ ДЕЛАТЬ ЭТОГО в производственном коде. Хотя это довольно сексуально, это злоупотребление основными принципами кодирования (например, "принцип наименьшего удивления" (хотя на самом деле это довольно интуитивный синтаксис) или "не повторяйся", особенно если упаковка реального заводского метода с некоторыми параметрами, что само по себе, кстати, уже является злоупотреблением DRY...), плюс PHP может измениться в будущем, чтобы таким забавным образом взломать код.
 0
Author: Sz., 2015-07-24 08:32:53