Pull to refresh
6
0

Пользователь

Send message
Все зависит от модели. Если логика сильно меняется от класса к классу, то возможно не стоит создавать базовый контроллер. Обычно хватает 2-3 методов в качестве точек расширения.
Согласен, надо подумать на этот счет, возможно, создать интерфейс для загрузчика, и в бандле получать все загрузчики, так же, как сейчас endpoint-ы.
Основная причина, почему routes() нестатический — чтобы при наследовании можно было использовать абстрактные методы.
Если в контроллере нет каких-то других параметров, типа имени класса, которые влияют на генерацию роутов, то лучше вынести в отдельный класс. Но могут быть и другие параметры, иногда довольно сложные, от которых зависит логика контроллера и которые не хочется раскрывать.
Добавил пример с наследованием.
Теоретически можно сделать ее статической, но при генерации роутов могут понадобиться сторонние сервисы, например, для получения конфигов.
Проблема решается примерно так:
<?php
use Doctrine\ORM\EntityManagerInterface;
use PaLabs\EndpointBundle\EndpointInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Route;

abstract class BaseEntityListController implements EndpointInterface {
    
    protected $em;
    
    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    protected abstract function className(): string;
    
    public function routes()
    {
        return new Route(sprintf("/rest/%s/list", $this->sectionName()));
    }

    public function execute(Request $request): Response
    {
        // do work
        $this->em->getRepository($this->className())->findAll();
    }
    
    protected function sectionName(): string {
        $reflection = new \ReflectionClass($this->className());
        return $reflection->getShortName();
    }
}

class SomeEntityController extends BaseEntityListController {

    protected function className(): string
    {
        return MyEntity::class;
    }
}
На этапе генерации кэша. Но теоретически можно брать конфигурацию из БД и на ее основе генерировать роуты (на целевом сервере). Правда, это все будет статически.

Основное преимущество — программная генерация роутов. Это важно, в частности, для наследования контроллеров. Но также полезно, если есть сложная логика генерации. В сторонних библиотеках этот бандо лучше не использовать.

В сложном случае да, но в простом случае, если надо только гарантированно закрыть соединения, вполне подходит вариант с набором deferred-обработчиков.
Такой подход есть во многих языках, try-with-resources. Он хорошо подходит в случае одного ресурса. Но в случае одновременной работы с несколькими ресурсами получается довольно громоздкие вложенные конструкции. Например, вам надо открыть какое-то (заранее неизвестное) число ssh-прокси соединений, и в конце обязательно закрыть их. Как в этом случае использовать with?
Да, всегда найдется способ использовать неправильно. Но использование замыкания в deferred() гарантирует, что обработчики в любом случае выполнятся после завершения замыкания.
Передать контекст во внутреннюю функцию иногда может быть полезно. Например, если в рамках какого-то процесса нужно создать несколько временных файлов, которые будут использоваться в разных местах процесса, а удалить все файлы нужно в конце процесса. В этом смысле Defer мощнее, чем в go.
Ваш вариант интересный. Но есть несколько моментов:
1) Я бы не стал полагаться на, что деструктор будет вызван когда нужно. Например, я могу передать $defer куда-нибудь еще, или сохранить в какой-то глобальной переменной, и тогда логика работы функций-обработчиков может нарушиться. Хотя для локального использования так даже проще
2) Обработчики нужно выполнять в порядке, обратном их добавлению
3) Нужно ловить исключения при вызове обработчика

В качестве замены трейту можно использовать что-то такое:
function deferred(callable $callback) {
    $context = new DeferredContext();
    try {
        $callback($context);
    } finally {
        $context->executeDeferredActions();
    }
}


И использовать:
deferred(function(DeferredContext $context){
   // Some actions 
});
В Gitlab CI обещают улучшить работу с артефактами — можно будет загружать артефакты от предыдущих задач в конвейере, наверное, будет апи, с помощью которого можно будет делать многое из того, что вы описываете. Ручного запуска билдов, насколько я знаю, нет. А build matrix есть, но она задается вручную перечислением задач.
С другой стороны, в Jenkins довольно тяжело работать с docker. А без него сложно обеспечить изоляцию билдов — например, на одном воркере тестировать проект с разными версиями python и mysql одновременно. И с автоматическим созданием воркеров в облаках непросто.
Что умеет Jenkins, чего не умеет, например, Gitlab CI?
Это если у вас ни в каком перечислении нету таких же значений. А если есть, к примеру,
class EventQueueStatusEnum extends AbstractEnumType
{
    const
        DRAFT = 'draft',
        STARTED = 'started',

 protected static $choices = [
        self::DRAFT => 'enum.eventQueueStatus.draft',
        self::STARTED => 'enum.eventQueueStatus.started',
}

то нужно явно указывать тип в readable_enum. Самое плохое то, что если раньше EventQueueStatusEnum не было, а потом его добавили, то все, что использовало EventStatusEnumType в виде tem.type|readable_enum|trans, сломается
Все зависит от задачи. В вашем случае, например, нету описания типа для разных БД. А значит, нет проверки значения на стороне БД.
А если есть 2 Enum-а с одинаковыми значениями, но разным переводом? Тогда в любом случае нужно указать его тип. А если где-то уже есть {{ item.type|readable_enum|trans }}, то и не забыть указать тип там.
Пока нет, приходится вручную менять комментарий к полю. Наверное, можно написать свой компаратор.
Это хороший бандл, но у него есть недостатки, важные для нас. В частности, значения перечисления там — строки. И при использовании в шаблонах нужно указывать тип перечисления, например readable_enum('BasketballPositionType'). Что создает проблемы при рефакторинге — нужно не забыть изменить шаблоны. А если значения перечисления — объекты, то можно не думать об этом и избежать ошибок, особенно в перечислениях с похожими значениями.

Information

Rating
Does not participate
Location
Новосибирск, Новосибирская обл., Россия
Registered
Activity