Konstantin
в конце концов можно сделать так (название метода выдуманное)
Konstantin
class User { updateNameSurnameAgeAndGender(string $name, string $surname, int $age, GenderEnum $gender): void { $this->name = $name; $this->surname = $surname; $this->age = $age; $this->gender = $gender; } }
Konstantin
то есть вызывающий код всегда знает что он делает, а не просто говорит "а обнови-ка юзера данными из этой формы", это чревато проблемами, когда что-то поменяется
Konstantin
или поменяется бизнес-логика: допустим, нельзя будет обновлять имя пользователю, что не подтвердил емейл. или если один раз сказал, что тебе меньше 18, то всё, поменять на "больше 18" нельзя
Konstantin
если обновление полей размазать по "клиентскому" (относительно репозитория/dbal) коду - концов в жизни не сыщешь
Konstantin
короче, чем уже интерфейс, чем жестче контракты - тем лучше. контракт "обнови такую-то сущность чем-то там" - очень мягкий
Gleb
О как, вот об этом не задумывался. И это очень хорошо объясняет почему так делать не стоит!
Юра
Так это надо по дто на каждый тип обновления?
Юра
Либо все поля нулабл делать
Konstantin
Так это надо по дто на каждый тип обновления?
скорее всего это почти точно не нужно. либо это форма о трёх-пяти полях (мы же тут не црм пишем, верно?), либо пяток возможных действий с одним юзером
Konstantin
типа подтвердить емейл, сменить имя
Konstantin
тьфу, я перегрелся. в смысле да, скорее всего это пяток дто + одна форма
Gleb
Скорее же на запись заполнить нужное, либо дефолтные значения. А при обновлении сначала получить сущность, исправить что надо сеттерами, потом в DTO и уже сохранять. Или я опять фигню придумал?
Konstantin
первый вопрос не понял, второе - да, это неизбежный трейдофф при использовании орм
Юра
Если бы без форм то наверное так надо делать UserDto::fromUser($user)->withName($newName)->withEmail($newEmail);
Konstantin
то есть в терминах орм мы оперируем объектами - не записями в базе, не таблицами, не базами, именно объектами
Юра
С формами просто по дто на каждую форму и $dto->updateUser($user);
Konstantin
таки наоборот, чтобы сеттерами не торчать наружу
Konstantin
то есть $user->updateFromSomeDto($dto)
Gleb
Первое это я снова туплю. В сущности User у меня к примеру поле #[ORM\Column(type: 'boolean', nullable: false, options: ['defaults' => false])] private bool $isActive; получается в DTO мне тоже надо продублировать дефолтное значение в false, ибо если будет null, то тогда в сущности я же словлю ошибку по идее. но тут мне начинает не нравится дублирование в обоих местах одного дефолтного значения. :(
Gleb
Блин... пока изучаешь - всё просто. Как начинаешь сам с нуля писать код и думать - фигня полная. 😂
Konstantin
private bool $isActive = false
Konstantin
вся row-specific логика находится в сущности
Юра
С формами просто по дто на каждую форму и $dto->updateUser($user);
А вот были бы friend классы можно было бы и так )
Konstantin
class User { updateFromDto(SomeDto $dto): self { $this->name = $dto->getName(); if (!is_null($dto->getFoo())) { $this->foo = $dto->getFoo(); } } }
Konstantin
А вот были бы friend классы можно было бы и так )
я думаю всё как-то паттерн builder для сущностей на анонимных классах сделать, чтобы сущность сеттерами не торчала
Konstantin
да и для гуззла, заело его options руками писать. всё время забываешь, то ли там form_data, то ли form_params и всё такое
Konstantin
кстати, гуд ньюс, ереван
Konstantin
я тут научился гуззл 7 настраивать чтобы эта ёбаная блядина писала нормальный ответ в случае ошибки, а не транкейтила его по 128
Konstantin
хотите, поделюсь, там не особо сложно, но в доках нихера нет, приходится по исходникам шариться
Юра
Давай. Бесит реально
Юра
Сложно им что-ли в конфигурацию вынести
Konstantin
GuzzleHttp\BodySummarizer: arguments: $truncateAt: 4096 http_errors_mw: class: \callable factory: [GuzzleHttp\Middleware, httpErrors] arguments: - '@GuzzleHttp\BodySummarizer' GuzzleHttp\HandlerStack: factory: [GuzzleHttp\HandlerStack, create] calls: - [push, ['@http_errors_mw', http_errors]] GuzzleHttp\Client: arguments: $config: handler: '@GuzzleHttp\HandlerStack'
Юра
Как можно вообще трункейтить текст ошибки и не давать возможности отключить
Konstantin
Сложно им что-ли в конфигурацию вынести
в 7 вынесли, но в доках не пишут. но гуззл пидарасы пишут, они сказали если вы это просите так сильно значит вы контрибуторов не уважаете, а следовательно идёте на хуй. контрибуторам виднее как писать. не нравится - не используйте
Konstantin
это примерно дословный перевод
Юра
Мне офигеть как нравится читать error in ....
Юра
Или please check that field....
Gleb
@sc0rp10 , спасибо большое! вопросы пока ещё остались, но скорее вида "а что если". Код накидаю, там сам пока поразбираюсь.
Konstantin
Или please check that field....
дада, в сентри с продакшна
Konstantin
когда хер воспроизведешь локально, а на проде стреляет раз в неделю
Vlad
middleware
The Ant
middleware
чо там?
Gleb
$this->foo = $dto->getFoo() ?? 'default value'; easy
Так старое доброе - зависит от версии php, вроде он только с 8.
Vlad
чо там?
в газле миддлваре из коробки
Vlad
или хочешь узнать зачем миддлаваре в клиенте?
The Ant
или хочешь узнать зачем миддлаваре в клиенте?
да, зачем они? если можно декорировать
Konstantin
чо там?
спасибо, я чуток умею в синтаксис. я этим примером хотел показать логику копирования значения из дто в сущность, типа если нужны какие-то ифы - писать это вот тут
Vlad
да, зачем они? если можно декорировать
ну к примеру авторизация на лету. Мутировать запрос как угодно, обработка ошибок и тд
Konstantin
юзаю симфони хттп клиент, норм же,зачем гуззле
да как-то так повелось,у нас относительно много кода гузл использует. в симфони-клиенте я не нашел ничего такого, чтобы прям взять и на него перейти. но мож не особо внимательно смотрел. если расскажешь в чем разница - будет круто
The Ant
типа в симфе по дефолту (я конечно же не проверял, но так заявлено)
Vlad
так и в sf клиенте аснук гавно
The Ant
чем?
Konstantin
ну асинк без костылей, в гуззле он как-то ебаное реализуется
в гуззле примерно все так, это да) архитектура и код там так себе
Vlad
чем?
ну то что его нельзя нормально использовать в async среде, я про amp/react. event-loop не может резолвить промисы данного клиента
The Ant
а, не юзал эти свули реакты
Konstantin
но я, увы, почти не использую асинк. типа если ты начнешь вместо ответа из сервиса промис возвращать, без женериков код моментально протухнет
The Ant
говняно да? ну кто бы мог подумать :D
Vlad
ну то что его нельзя нормально использовать в async среде, я про amp/react. event-loop не может резолвить промисы данного клиента
да и толку этого async в клиенте? Ну сходил в апи асинхронно и что дальше? Писать в бд с помощью пдо?
The Ant
джинерики лишь покажут ожидания, а что реально там прилетит хз ваще
Konstantin
джинерики не решат проблему
можно будет из сервиса возвращать Promise<User>
Konstantin
а щас - просто Promise
Konstantin
да и толку этого async в клиенте? Ну сходил в апи асинхронно и что дальше? Писать в бд с помощью пдо?
асинк надо когда ты собираешь страницу из ответа двух десятков микросервисов, причем часть запросов не зависит от результатов других. то есть их можно параллелить
Vlad
параллелизм =! асинхроность
Vlad
можно будет из сервиса возвращать Promise<User>
да благодаря файберам можно и без промисов, просто :User
Юра
можно будет из сервиса возвращать Promise<User>
В Котлине упоролись и возвращают не промис а сразу результат
The Ant
Юра
И понять что это асинк вызов можно только по иконке иде
Konstantin
параллелизм =! асинхроность
да, спасибо. но сделать параллельно несколько запросов в пхп можно только с помощью курл_асинк
Konstantin
или мульти, как оно там