Комментарии 25
Всем любителям Symfony известно что в ней нету компонента фильтр.


http://symfony.com/doc/current/components/options_resolver.html и filter_var, а так же фильтры твига (для фильтрации при выводе) полностью закрывают все юзкейсы.

а как вы решаете задачи по фильтрации в Symfony?

Не фильтрую. Только при выводе. trim-минги формы сами делают, иногда можно в сущностях что-то пофильтровать, но это именно какие-то бизнес-ограничения и деталие реализации сущностей и там этим вещам и место. А так это просто не нужно. Ну или у меня таких задач нет.
Думаю Вы просто мало с этим стыкались. Пример: как легко и просто можно фильтровать данные которые вы получаете от пользователя в написаном вами API? Или фильтрация данных из entity когда entity нужно передать в serializer/сторонний api?
Для начала давайте разберемся, какая у меня позиция относительно фильтрации данных в сущностях. Фильтровать данные в сущностях должны сами сущности (то есть я их тех людей, которые против использования сеттеров, анемичной модели и прочей чуши). У меня сущности это полноценные объекты предметной области, а не тупые структурки данных.

Далее…

как легко и просто можно фильтровать данные которые вы получаете от пользователя в написаном вами API?


Из такого рода «фильтрации» мне нужно только trim строк. Предложите мне другие ситуации когда это нужно?
Конкретный пример из жизни. У вас есть объект который вы получили с сервиса/базы данных которую редактировать у вас нет доступа. В объекте нужно отфильтровать несколько полей перед тем как передать конечному клиенту/сервису.
Исходя из вашего личного правила что в set/get можно писать фильтрацию и подобные вещи эта проблема решаема. Но куда удобней добавить одну аннотацию к property вместо нескольких строчек кода. Особенно если у вас много таких объектов и они совсем не маленькие. С моим решением как минимум станет легче читать код.
Вы не поняли. Что именно мне нужно фильтровать? Вот… серьезно, я не могу придумать.

Исходя из вашего личного правила что в set/get можно писать фильтрацию


Мое правило — нет никаких get/set в сущностях (только очень редко геттеры и только те что нужно). Есть только объекты предметной области, полноценные сущности с логикой внутри.

Особенно если у вас много таких объектов и они совсем не маленькие.

В большинстве случаев жирные объекты с большим количеством полей свидетельствуют о недостаточном уровне декомпозиции.
>В большинстве случаев жирные объекты с большим количеством полей свидетельствуют о недостаточном уровне декомпозиции.
Да но вы же не можете повлиять на нормализацию сторонней базы данных.

>Что именно мне нужно фильтровать? Вот… серьезно, я не могу придумать.
Например:
— в varchar хранится int и вам именно int нужно передать дальше.
— есть текст с переносами \n вам нужно сделать
— есть html а нужно передать text
— есть datatime а нужно timestamp
Да но вы же не можете повлиять на нормализацию сторонней базы данных.


Я могу мэпить ее на ту структуру объектов с которой мне приятно работать. В прочем у меня нет задач таких где я «не могу на что-то влиять» в плане структуры базы.

далее.

— каст типов — OptionsResolver
— это «фильтрация» при выводе, с этим нет никаких проблем. К сущностям не имеет отношения и к хранению тоже.
— есть html а нужно text — так же фильтрация строго при выводе. К сущностям не имеет отношения и к хранению тоже.
— есть datetime а нужно timestamp — вопрос фильтрации вывода. К сущностям не имеет отношения и к хранению тоже.
А как можно удобно фильтровать данные при вывод если вы используете Serializer + FOSRest?
С учетом того что выводимые данные в таком случае описываются в модели http://jmsyst.com/libs/serializer/master/reference/annotations
Я настрадался с сериалайзерами и просто использую fractal. Да и с symfony serializer я просто свои хэндлеры объектов писал. Код выходит мегаскучный, зато предсказуемый.
Ну и да, для справки. JMS Serializer — старый, не поддерживается уже года два, в нем куча багов и «ускорения разработки» с ним нет никакого. Я его 2 года использовал, мне надоело.
Но есть же проекты которым уже не один год) В таких случаях достаточно сложно перейти на что то другое.
Под выводом подразумевается хелпер твига? Где хранится код трансформации? В самом хелпере или хелпер просто проксирует запросы на другие объекты, передаваемые в хелпер через DI?
Чта?

Фильтры твига нужны там где есть твиг. А фильтровать тот же HTML в API не нужно, это сделают на клиенте.
Ну между json_encode и mysql_fetch_assoc еще гидрации Doctrine и много других веселых этапов. В частности надо же как-то еще DateTIme сериализовать в формате ATOM и т.д. Но это не фильтрация.
Отвечу за автора: эту задачу можно решить с помощью Data Transformer`ов, «запихнув» фильтрацию в этот слой, но сами трансформеры задачу не решают. Автор же предлагает простой вариант с аннотациями, для быстрой разработки и простого понимания
Дык можно решить, или трансформеры задачу не решают?

Насчет понимания я бы поспорил. Валидация в двух местах теперь, рано или поздно это где-нибудь аукнется. Насчет быстрой разработки, тут спорить не буду, но быстро не всегда значит правильно.
Мою задачу одними Data Transformer`ами не решить. Они работают для форм, но любой объект ими не отфильтруешь. Например есть база данных сторонняя и нету возможности изменять её формат и данные, но получать информацию можно. В моем решении можно отфильтровать любой объект с аннотациями в любой нужный момент.
Я так понимаю вам фильтровать надо, чтобы потом дальше передавать куда-нибудь? Во View, или куда-нибудь в др. место?

Расскажите как вы будете это делать если у вас один компонент допускает только br в name сущности, другой компонент допускает только b в name сущности. Сущность одна, приемников несколько, но в пропертях вы можете задать только один фильтр. Ваши действия?

Лично мое мнение, подобные преобразования должны происходить ближе к «выводу» и знания, как будет модель преобразовываться точно должны быть не в модели. Например View знает, что что-то надо показывать raw, а что-то с escape.

В общем на мой взгляд спорное решение.
> Расскажите как вы будете это делать если у вас один компонент допускает только br в name сущности, другой компонент допускает только b в name сущности. Сущность одна, приемников несколько, но в пропертях вы можете задать только один фильтр. Ваши действия?

Использовать группы фильтрации. Ровно так же как это сделано с валидацией.

> В общем на мой взгляд спорное решение.
Исходя из ваших слов выходит что и Constraint в symfony сделаны не верно.

Я долго работал с Zend и после перехода на Symfony самое первое что мне бросилось в глаза это простота/удобство аннотаций. Раньше я все валидации/фильтрации делал в формах и не могу сказать что это удобно.
Constraints это скорее для более удобной работы со схемой. Мне кажется тут больше надо смотреть в сторону Data Transfer Object.
Если задачу решить через трансформеры, то это будет так же «в двух местах», только при этом в двух совсем разных местах. А в случае автора, если он использует аннотации, то «валидация» хоть и будет два раза, но описана она будет в одном месте, что имхо лучше.
В этом и беда, что в одном месте. Например, переносы строк для вывода в теге «p» проходят через «nl2br», а вот при выводе в форме нужно использовать «htmlspecialchars», но никак не «nl2br».

Подобную логику нельзя сунуть в модели, можно делать отдельный сервис в стиле декоратора вроде view presenter или data transformer
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.