"Встроенный" класс в PHP? (Для удобства цепочки методов) - PullRequest
9 голосов
/ 10 октября 2008

Идиома, обычно используемая в ОО-языках, таких как Python и Ruby, - создание экземпляра объекта и создание цепочек методов, которые возвращают ссылку на сам объект, например:

s = User.new.login.get_db_data.get_session_data

В PHP возможно повторить это поведение так:

$u = new User();
$s = $u->login()->get_db_data()->get_session_data();

Попытка следующих результатов в syntax error, unexpected T_OBJECT_OPERATOR:

$s = new User()->login()->get_db_data()->get_session_data();

Похоже, что этого можно достичь с помощью статических методов, что, вероятно, я и сделаю в конечном итоге, но я хотел проверить lazyweb: Есть ли на самом деле простой, простой способ создания экземпляров классов PHP "inline "(как показано в приведенном фрагменте) для этой цели?

Если я решу использовать статические методы, не слишком ли волшебно, чтобы статический метод класса возвращал экземпляр самого класса ? (Эффективно писать свой собственный конструктор, который не является конструктором?) Это кажется грязным, но если не так уж много страшных побочных эффектов, я мог бы просто сделать это.

Полагаю, я мог бы также создать экземпляр UserFactory с помощью метода get_user (), но мне любопытно найти решения для того, что я спрашивал выше.

Ответы [ 6 ]

12 голосов
/ 10 октября 2008

Все эти предложенные решения усложняют ваш код, чтобы изогнуть PHP для достижения некоторой синтаксической сложности. Желание, чтобы PHP был чем-то, что не является (например, хорошим), - путь к безумию.

Я бы просто использовал:

$u = new User();
$s = $u->login()->get_db_data()->get_session_data();

Это ясно, относительно кратко и не содержит черной магии , которая может вносить ошибки.

И, конечно, вы всегда можете перейти на Ruby или Python. Это изменит вашу жизнь.

  • И да, я суров в PHP. Я использую это каждый день. Использую его годами. Реальность такова, что он имеет аккрецию , а не был спроектирован, и это видно.
8 голосов
/ 10 октября 2008
<?php

    class User
    {
        function __construct()
        {
        }

        function Login()
        {
            return $this;
        }

        function GetDbData()
        {
            return $this;
        }

        function GetSession()
        {
            return array("hello" => "world");
        }
    }

    function Create($name)
    {
        return new $name();
    }

    $s = Create("User")->Login()->GetDbData()->GetSession();

    var_dump($s);
?>

Это возможное решение :) Конечно, вы должны выбрать лучшее имя для функции ...

Или, если не возражаете, немного накладных расходов:

<?php

    class User
    {
        function __construct($test)
        {
            echo $test;
        }
...
    }

    function CreateArgs($name)
    {
        $ref = new ReflectionClass($name);
        return $ref->newInstanceArgs(array_slice(func_get_args(), 1));
    }

    $s = CreateArgs("User", "hi")->Login()->GetDbData()->GetSession();

    var_dump($s);
?>
5 голосов
/ 16 сентября 2009

Нет причин объединять хак (чтобы обойти проблему синтаксиса) и сам код создания объекта.

Поскольку новое выражение не может использоваться в качестве левого члена вашего оператора объекта, но выражение вызова функции может, вам нужно только обернуть ваш объект при вызове функции, которая возвращает свой собственный аргумент:

function hack($obj) { return $obj; }

$mail = hack(new Zend_Mail())
  -> setBodyText('This is the text of the mail.')
  -> setFrom('somebody@example.com', 'Some Sender')
  -> addTo('somebody_else@example.com', 'Some Recipient')
  -> setSubject('TestSubject');
5 голосов
/ 10 октября 2008

Единственный способ получить нечто похожее - использовать фабричный или одноэлементный статический метод. Например:

class User
{
    //...
    /**
     *
     * @return User
     */
    public static function instance()
    {
        $args = func_get_args();
        $class = new ReflectionClass(__CLASS__);
        return $class->newInstanceArgs($args);
    }
    //...
}

Это использует API отражения PHP5 для создания нового экземпляра (используя любые аргументы, отправленные в :: instance ()) и возвращает его, позволяя вам создать цепочку:

$s = User::instance()->login()->get_db_data()->get_session_data();

Между прочим, этот код достаточно гибок, и единственное, что вам придется изменить при копировании этого статического метода, это @ return комментария PHPDoc.


Если вы хотите преждевременно оптимизировать свой код, как наш друг Нельсон, вы можете заменить содержимое User :: instance () на:

return new self();
3 голосов
/ 14 марта 2014

Простой ярлык на

$Obj = new ClassName();
$result = $Obj->memberFunction();

это

$result = (new ClassName())->memberFunction();
1 голос
/ 27 июля 2015
<?php 
//PHP 5.4+ class member access on instantiation support.
$s = (new User())->login()->get_db_data()->get_session_data();
...