Intereting Posts
принимать POST только с собственного сервера Несколько серверов и Memcached Функция PHP password_hash солевой длины 21 или 22? Класс 'MyChat \ Chat' не найден в C: \ wamp \ www \ bin \ chat-server.php Запрос Curl с дайджестом auth в PHP для скачивания Частный репозиторий Bitbucket Как проверить наличие экземпляра wget sonataNotificationBundle, электронные письма, которые хранятся в базе данных, но потребитель swiftmailer не запускается, и никакие электронные письма не отправляются Передача данных из $ ajax-вызова в highcharts MYSQL получает все сгруппированные результаты по одному запросу с подсчетом строк Как предотвратить Предупреждение: длина содержимого и размер памяти POST Сессия Laravel отсутствует после обновления страницы Каков наилучший способ проверить, существует ли URL-адрес в PHP? Изображения кэша в скрипте php Создание мобильного приложения в Symfony2 WooCommerce исключает определенные атрибуты продукта на странице магазина

«Inline» Class Instantiation в PHP? (Для удобства цепочки методов)

Идиома, обычно используемая в языках OO, таких как 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 (), но мне интересно, какие решения я попросил выше.

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

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

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

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

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

  • И да, я суров на PHP. Я использую это каждый день. Использул его в течение многих лет. Реальность такова, что она расширилась , а не была спроектирована и показана.
 <?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); ?> 

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

 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(); 

Кстати, этот код достаточно гибкий, что единственное, что вам придется изменить при копировании этого статического метода, – это комментарий @Durnurn от PHPDoc.


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

 return new self(); 

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

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

 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'); 

Простой ярлык для

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

является

 $result = (new ClassName())->memberFunction(); 
 <?php //PHP 5.4+ class member access on instantiation support. $s = (new User())->login()->get_db_data()->get_session_data();