Как стать автором
Обновить

Комментарии 27

А теперь о реализации, а точнее про тайпхинт «object»:

1) Тайпхинт object доступен начиная с PHP 7.2, однако почти все фреймворки используют в минималках 7.1
2) object не доступен для перегрузки, а значит вот такое просто невозможно:
class Dispatcher implements EventDispatcherInterface
{
    public function dispatch(EventInterface $event) { ... }
    // Fatal error:  Declaration of Dispatcher::dispatch(EventInterface $event) must be compatible with EventDispatcherInterface::dispatch(object $event)
}

Как следствие — куча оверхеда и минус консистентность.

Выводы, думаю, очевидны: PSR-14 — в текущем виде печален и не удивительно, что Фабьен ушёл из PSR после принятия 14го.
Давайте искать плюсы. Фреймворки подтянут минимальную версию php до 7.2. Это же хорошо. А по поводу object это конечно слишком общно. Но с другой стороны, а какой интерфейс должен быть о Event? И чтобы всем подошло. Я думаю это тема будущих дискуссий.
Фреймворки подтянут минимальную версию php до 7.2. Это же хорошо.

Лишь в следующих мажорных релизах и то вряд ли. И это не плюс, а скорее минус: Мы получаем уменьшение количества поддерживаемых версий PHP из-за одного единственного интерфейса, т.к. объективно 7.2 (как и 7.3) проходные версии, которые ничего особо нового не добавляют и следующий инкремент с 7.1 оправдано делать лишь на 7.4, т.к. там огромное количество киллерфич добавляется.


Но с другой стороны, а какой интерфейс должен быть о Event? И чтобы всем подошло. Я думаю это тема будущих дискуссий.

С другой стороны а нужен ли вообще этот PSR-14? У разных фреймворков разные реализации. У Symfony, например, события именованные и внедрение PSR-14 ломает вообще всю обратную совместимость. У Laravel и Zend вообще события содержат обычный массив и тут ситуация ещё хуже.


А если уж делать PSR полностью, то где вообще addListener, removeListener, и прочее?


Хорошо, вот ещё пример проблем PSR-14: Почему вообще getListenersForEvent должен содержать объект?


// Метод из диспатчера Symfony в качестве примера добавления листнера
$dispatcher->addListener(SomeEvent::class, function () { ... });

// Получение листнеров из Symfony
$dispatcher->getListeners(SomeEvent::class);

// А это уже PSR
$dispatcher->getListenersForEvent(new SomeEvent()); // Нахрена тут объект?
$dispatcher->getListenersForEvent(new SomeEvent()); // Нахрена тут объект?

Видимо решили так сделать, чтобы диспатчер и/или листенеры могли отличать экземпляры событий одного класса, по event type или event source еще как-то, хз, в зависимости уже от конкретной реализации. Я тоже удивился когда там объектный тайпхинт увидел.
Видимо решили так сделать, чтобы диспатчер и/или листенеры могли отличать экземпляры событий одного класса, по event type или event source еще как-то, хз, в зависимости уже от конкретной реализации.

Для этого и у Zend, и у Laravel, и у Symfony и, наверняка, ещё у кучи других есть имя события. Так что можно было бы сделать запросто вот так:


interface EventInterface
{
    public function getName(): string;
}

interface EventDispatcherInterface
{
    public function dispatch(EventInterface $event);
}

interface ListenerProviderInterface
{
    public function getListeners(string $name): iterable;
}
НЛО прилетело и опубликовало эту надпись здесь

Да, я вижу что в dispatch можно передать что угодно, хоть stdClass… Но если это допустимо, то почему нельзя передать строчку? Или массив? Если не делать ограничений на типы объекта, то почему нужно ограничивать объектом? Ну ладно, опустим этот момент.


А теперь главный вопрос: Вот вы совершенно правильно говорите, что идентификатор должен детектить провайдер, который используется внутри диспетчера. А нахрена в PSR нужен интерфейс провайдера, который является частным случаем реализации диспатчера, должен использоваться только внутри него и совершенно не пригоден для использования вне? PSR как бы про публичные интерфейс, которые дёргаются внутри пользовательских приложений.

PSR как бы про публичные интерфейс, которые дёргаются внутри пользовательских приложений.

Не совсем про это они, имхо. Они, скорее, по совместимость компонентов фреймворков, а не про предоставление пользователям фреймворков (разработчикам пользовательских приложений) единого публичного API, чтобы они могли легко писать framework agnostic приложения.

Совместимость компонентов фреймворков? Это чтобы использовать ListenerProviderInterface из зенда и подсовывать его в EventDispatcherInterface из ларки? Именно для таких задач этот провайдер существует?


Ну… Это не то что странно… Это вряд ли вообще кому-то вообще нужно, скажем так.

Типа того. Для событий сложно сходу придумать, поскольку новый интерфейс, но, например, логгер с PSR-3: есть в симфони, есть в зенде реализации, есть monolog (сам по себе фреймворк для логгинга), есть в друпале, есть в yii работа с psr-3. Или middleware. Или response-request. Внедрённые во фреймворки стандартные интерфейсы позволяют малой кровью собирать свой фреймворк из компонентов разных вендоров, своих или, например, плавно мигрировать с одного фрейма на другой.

В случае psr-3 берётся LoggerInterface и без каких-либо изменений всовывается в любой фреймворк. Это как раз публичный интерфейс, который можно запросто дёргать и напрямую без всяких обвязок и подмена реализации на другую ничего не изменит. Миддлвари имеют примерно такую же цель. Про этот интерфейс разработчик знает и активно может использовать.


А вот EventDispatcherInterface — это внутренняя и частная реализация диспатчера, которая никуда не торчит. Что мы потеряем если вообще удалим этот интерфейс? Какую переносимость потеряем и что не сможем сделать?

НЛО прилетело и опубликовало эту надпись здесь

С таким же успехом, перефразируя, можно спросить про то, зачем ему знать об объекте, ведь событием может быть и массив, и строка… Не правда ли? Zend и Laravel тому в пример.


P.S. Но с другой стороны понятна причина добавления тайпхинта, т.к. есть вот такой RFC: https://wiki.php.net/rfc/covariant-returns-and-contravariant-parameters Позволяющий сузить область при наследовании и указать конкретный тип. Но… Но мы возвращаемся к первому моему примеру с EventInterface, чем он в таком случае не угодил? Пусть даже с пустой реализацией, но мы сразу же выкинем из под категории "событие" весь stdlib php и все вендорные классы, которые не являются потомками EventInterface

НЛО прилетело и опубликовало эту надпись здесь

Когда буду алгебраические типы, тогда можно будет. Мои попытки написать RFC на эту тему закончились тем, что их внедрение потребует дохрена всего. Очевидно, что подобные вещи надо внедрять постепенно и ковариантные тайпхинты вполне себе первый шажок в этом направлении.

НЛО прилетело и опубликовало эту надпись здесь
Основные училия сейчас направленны на ФФИ. Лично меня они радуют. Должы и Вас. Потому что можно будет писать свой новый ПХП по верх стандартного.

Это вы про бесподобный пост от ircmaxell?

НЛО прилетело и опубликовало эту надпись здесь

Тут, по-хорошему, дженерики нужны. Если бы они еще были...

2. Возможно, с этим и боролись. Т.к. здесь у пакета появляется дополнительная зависимость в виде EventInterface. А для большей переносимости лучше, чтобы аспекты реализации не хранились в интерфейсе.
Во всяком случае их мысль я понимаю именно так.
И как можно универсально использовать эти интерфейсы без универсального формата события? Это всё равно что стандартизировать strpos(string, string), но не указать в какой строке какая строка ищется.

а я не особо понимаю чем отличается от паттерна наблюдателя и почему не используются встроенные spl интерфейсы

да, мне тоже напомнило, наверное тут будет обобщенно все называться
Я не понимаю, а как же реализовывается приоритет обработчиков для одного события?

скорее всего в getListenersForEvent, если нужно.
как тут писали выше, слишком все какое-то абстрактное #comment_20125570

НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий