Pull to refresh
4
0
Александр @BoShurik

Symfony-разрботчик

Send message

Еще раз… Для Symfony ваш пакет бесполезен, т.к. .env загружается всегда, а .env.local не содержит всех параметров.


Даже если представить, что разработчик добавил новый параметр в .env.local и забыл его указать в .env, ваша утилита генерирует неверный код:


.env (aka .env.example)


FOO=foo
BAR=bar
BAZ=baz

.env.local (aka .env)


# перезаписанный параметр
FOO=my-foo 
# новый параметр
NEW=new 

У вас генерируется:


FOO=null
NEW=null
Для локальной разработки нужно скопипастить содержимое файла .env в файл .env.local и заполнить значение ключей.

Идея как раз в том, что копировать содержимое не нужно, а только тех переменных, которые отличаются. К примеру, APP_NAME, порты БД, Redis etc дублировать нет смысла

В Symfony — не так: https://symfony.com/doc/current/configuration.html#overriding-environment-values-via-env-local


Описание изменений https://symfony.com/doc/current/configuration/dot-env-changes.html


Из плюсов:
Не надо переназначать все переменные, а только те, которые отличаются.
Если добавились новые параметры они автоматом подтянутся.

Мне кажется привязка к Eloquent не обязательна. Если передавать массив параметров вместо одной сущности, то область применения расширится


$tempFileName = $printFormProcessor->process($templateFile, $parameters = [
    'entity' => $entity,
    'now' => new \DateTime(),
]);
  1. Я все-таки в уме держу некоторую абстракцию, где кеш может быть не только в redis, где такого флага может не быть
  2. И вот как раз в ситуации большого количества запросов TTL1 < t < TTL2, когда запрос на перегенерацию уже отправлен, но еще не выполнен, есть вероятность получить много таких холостых перегенераций

Я так понял, вашем случае защиты сервера нет. Когда одновременно прилетает 100500 запросов на одно кеш-значение, да, вы быстро отдадите пользователю ответ, но при этом 100499 раз избыточно перегенерируете кеш.

Как правило это фантазии и 99% мапиться 1 к 1, а если не мапится, то это ошибки архитектуры. Примеры кидайте.

Недавно была задача: при регистрации заполнять анкету. По факту часть полей формы использовалась для генерации документов и в таблицу в итоге не уходила. При этом форма достаточно большая плюс присутствовала загрузка файлов поэтому, кстати, было отдельное требование, чтобы вся валидация была на фронтенде.


Еще немаловажный факт, что валидные данные нам нужны до вставки в БД.


Пример
{
    "username": null
}

class UserDTO
{
    /**
     * @var mixed
     *
     * @Assert\NotBlank()
     * @Assert\Type("string")
     */
    public $username;
}

class User
{
    /**
     * @ORM\Column(type="string")
     */
    private string $username;

    public function __construct(string $username)
    {
        $this->username = $username;
    }
}

$dto = $this->serializer->deserialize($json, UserDTO::class, 'json');
$user = new User($dto->username); // PHP Fatal error:  Uncaught TypeError
$this->entityManager->persist($user);
$this->entityManager->flush();

Как много проектов вы реализовали с таким подходом? Судя по packagist, это очень похоже на концепт, который нигде не применяется, даже вами...


На практике все равно придется иметь отдельную от БД библиотеку для валидации, т.к. база не покрывает всех кейсов. При этом проверка на уникальность в 99.99%, как вы сами сказали, сработает и в стандартном валидаторе. Я, к примеру, ни разу не встречал зафейленные таким образом запросы. И получается, что не будет единого источника правды: за тем, чтобы узнать реальные правила валидации надо будет всегда заглядывать в оба места. Лично мне это не удобно, т.к. смена контекста код — база очень напрягает.


Это все не обращая внимания на то, что DTO с которым работает пользователь маппится на базу не один к одному. К примеру, в БД поле name, а от пользователя приходит firstName, lastName и middleName.


Уверен, на 100%, если бы какая-нть, из выше указанных библиотек в статье, совместила свою поделку с разработанным мною принципом Database First, то она стала бы отраслевым стандартом.

В symfony/validator есть нечто похожее

Вопрос конечно что делать если какое то свойство было, а потом его не стало

При любом подходе это будет проблемой.В общем случае свойство будет инициализировано null


а вообще такое бывает, что иногда один набор параметров в ответе, иногда другой.

Если говорить о symfony/serializer, то это решается кастомным нормалайзером


И как бы из CSV делать объекты, если у CSV структура вариативная, у одного файла такие колонки, у другого чуть чуть другие.

Для одного файла один объект, для другого — другой.

Но чтобы VARCHAR(4) применился нам эти данные придется транкейтить вручную. Как при таком подходе уменьшить разрешенную длину строки, но чтобы старые данные остались неизменными?

CREATE TABLE test (name VARCHAR(8)) ENGINE=INNODB;
INSERT INTO test (`name`) VALUES ('12345678');
ALTER TABLE test CHANGE name name VARCHAR(4);

Есть примеры таких SPA? Вот смотрю сейчас на twitter.com. Сам документ вернулся за 196мс + основной контент ленты пришел за 865мс

БД тут не при чем. Как, к примеру, отвалидировать такую форму?


$form = [
    'bik' => '044525600',
    'rs' => '40702810400260004426',
    'ks' => '30101810300000000600',
];

Валидность rs и ks в данном случае зависит от bik.

Еще частый юзкейс: валидация на базе всех введенных данных. К примеру, для валидация р/с и к/с надо знать значение БИК. На первый взгляд rakit/validation так не умеет.

А такие коммерческие решения уже существуют?

Я ниже ответил подробно. Как раз из-за того, что вы смешали два способа реализации формы: форма сгенерированна под аутентификатор, а в итоге используется form_login, вам пришлось искать эти параметры.

В Symfony есть несколько способов реализовать форму входа:


  1. Изначальный form_login. По сути требует от себя только небольшого конфига


    form_login:
        login_path: login
        check_path: login

    и собственно самой формы. К сожалению, шаг влево, шаг вправо — она уже не подойдет (хотя мне всегда хватало)


  2. Аутентификация на базе symfony/security-guard. В этом случае у пользователя есть полный контроль над процессом, но требует от себя больше действий, а именно реализации интерфейса AuthenticatorInterface. Как раз этот способ предлагается в документации, т.к. используется MakerBundle и весь бойлерплейт можно переложить на кодогенерацию.



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

Во-первых, вы выбрали это решение потому что у вас уже были наработки. Думаю большинство разработчиков поступили бы так же и были бы правы.


В случае, если таких наработок нет, я и предложил свой вариант.


В идеальном случае будет что-то вроде:


composer req symfony/messenger symfony/mailer symfony/notifier
composer req symfony/*-mailer symfony/*-notifier

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


Если нужного транспорта нет, то да, придется его реализовать (как, впрочем, и в вашем случае), что в общем-то тривиально (e.g. symfony/free-mobile-notifier)


1) простую очередь (замечу, что ее можно использовать не только для рассылок)
2) изолированный микросервис для рассылок (легковесный, 8мб в докере)
3) используем go либу для амазона, и пишем GET/POST запрос для отправки СМС куда душе угодно
У вас же 2 библиотеки минимум + та же самая очередь потребуется (для асинхронной рассылки) + также надо имплементацию писать.

Плюс-минус одинаково, разве нет? В моем варианте используются абстракции в рамках php, а в вашем — конкретные библиотеки для конкретных решений, разнесенные по разным языкам.


В вашем же кейсе возникают вопросы — как прикрутить 2 аккаунта, как добавить рейт лимитер. Как прикрутить рейт лимитер к рассыльщику и т.п.
Так ваш проект начнет уже на старте обрастать тех долгом, костылями.

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


Решение из коробки это классно, но только если вы на 100% уверены что не придется его масштабировать.

По факту вам не понадобился ни рейт лимитер, ни 2 аккаунта, т.е. в рамках задачи можно было бы использовать и решение из коробки :)

Information

Rating
Does not participate
Location
Владимир, Владимирская обл., Россия
Date of birth
Registered
Activity