LINUX.ORG.RU

Все что нужно знать о Symfony.

 ,


0

1

Я много пишу PHP кода и часто слышу, что Symfony, это прямо right-way в разработке, что там нет связанности и так далее.

Если это так, то почему в ControllerTrait (который используется в AbstractController) есть метод getDoctrine()? Хм, неужели доктрина прибита гвоздями к фреймворку?

А чем UserRepository::findById(100) хуже чем:

$this->entityManager->getRepository(User::class)->findOneBy(['id' => 100]);

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

Далее. Все Entity прибиты к Doctrine через аннотации. Подход ничем не лучше AR из того же Yii2 или Laravel. Захочешь перенести модель в другой фреймворк - замучаешься вычищать код. Что делать? Добавлять еще одну абстракцию!

Symfony security завязан на Doctrine.

Вот такое наблюдение от разработки проекта на Symfony.

В итоге у меня в проекте есть дополнительный слой абстракции над Doctrine, чтобы к ней не привязываться лишний раз.


Ответ на: комментарий от Twissel

Точнее было бы сказать, что фреймворк прибит к Доктрине, не?

Видимо, пользуется оттуда какими-то компонентами. Насколько много — не знаю. Не пользовался ни тем, ни другим :)

KRoN73 ★★★★★
()

А какие плюсы у Laravel в сравнении с Symfony?

$this->entityManager->getRepository(User::class)->findOneBy(['id' => 100]);

Зачем это «прятать»?

Зачем заботиться о «переносе кода в другой фреймворк», откуда эта потребность переносить бойлерплейтный код?

anonymous
()

Zend Famework 3, конечно, намного более «right-way в разработке» чем Symfony, но за работу с последней мне деньги платит... Что касается этих зависимостей, да, смотрится тупо, но ведь совсем не обязательно их использовать. Например, Doctrine в контролере да и вообще autowiring сервисов - такой фигнёй в работе я не пользуюсь, так что все тобой упомянутые гвозди отпадает. Вместо аннотации можно использовать более кошерный XML. Если дополнительные возможности фрэймворка делает код запутанным, от них почти всегда можно отказаться, что тебе и советую.

anonymous
()

Ну и идем дальше:

 protected function isGranted($attributes, $subject = null): bool
    {
        if (!$this->container->has('security.authorization_checker')) {
            throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".');
        }

        return $this->container->get('security.authorization_checker')->isGranted($attributes, $subject);
    }

Это код из ControllerTrait.php, соответственно у нас в контроллере есть метод $this->isGranted() и я так понял он будет даже в случае, если у нас security-bundle не установлен. Это right-way?

Почему нельзя сделать по нормальному:

public function someAction(AuthorizationCheckerInterface $security)
{
    if ($security->isGranted(...)) {
       // ....
    }
}

И все! Есть security-bundle у нас - ок, нету - ну и ладно, мы его не используем.

Может вы заметили мой «тон», но меня уже несколько дней бомбит от Symfony. Я до этого работал с Laravel/Yii2, а теперь делаю довольно сложный проект на Symfony. Как раз по right-way и по их доке.

К Laravel/Yii2 у меня не было никаких претензий. Это RAD. Особенно Yii2. Samdark это признает. И это хороший фреймворк, если не использовать в своих моделях Yii::$app и так далее.

Symfony я использовал по минимуму, но везде читал, что это чуть ли не единственный правильный фреймворк и тут такое.

И я вот прям чувствую, что меня где-то с Symfony наеобманули

fman2
() автор топика
Последнее исправление: fman2 (всего исправлений: 2)
Ответ на: комментарий от fman2

ControllerTrait.php - чтоб было быстро(!), ехало и бибикало. Если в нём спрятанная магия тебе не подходит, тебе совсем не обязательно от него производных наследовать, чтоб сделать свой няшный контроллер. Можно даже, пользуясь системой событий, сделать такой контроллер, чтоб он вместо Request/Response принимал и отдавал уже подготовленные данные в виде Entity например. А вот превращением Request в Entity и контролерром вернутого Entity в Response занимались отдельные модели. Возможностей - море. :)

anonymous
()
Ответ на: комментарий от fman2

Это код из ControllerTrait.php, соответственно у нас в контроллере есть метод $this->isGranted() и я так понял он будет даже в случае, если у нас security-bundle не установлен. Это right-way?

нет, это изкоробочный RAD подобный сахар. Ненужно? не используй.

Почему нельзя сделать по нормальному:

а кто тебе запретил это сделать?

Noob_Linux ★★★★
()
Ответ на: комментарий от anonymous

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

umren ★★★★★
()
Ответ на: комментарий от umren

Тебя не смущает что у популярных пакетов 100500 зависимостей от всякого мусора вычисляющего 2+2 и написанного noname васянами?

anonymous
()
Ответ на: комментарий от umren

И сколько это времени займет? Раза в 2 дольше, чем на php писать

NetSurf
()
Ответ на: комментарий от fman2

по нормальному
public function someAction(AuthorizationCheckerInterface $security)

А с чего ты решил, что передавать в каждый чих какую-то херь (в данном случае аус-чекер) — это «по нормальному»? Или там, о чём ты, это лучший из ненормальных вариантов? Допустим, но этим проблему не решить, ведь тут она только поднимается на уровень выше, т.е. требует где-то перед вызовом ещё озаботиться получить этот чекер. Но это сейчас, локально, лишь о чекере речь, а подумай о других ситуациях.

deep-purple ★★★★★
()
Ответ на: комментарий от NetSurf

Из коробки не умеет сериализовать Entity в массив когда нужно.

К примеру, в Yii2 можно было написать в контроллере:

// $user - некий экземпляр класса User (к примеру)
$user = UserRepository::findOne(1);
return [
    'user' => $user
];

Это быстро, удобно, но есть проблема - модели у нас не чистые, а наследуются или от AR или от Model. И того у нас получается преобразование - массив - AR - массив

В Symfony наши сущности чистые (не считая хлама с аннотациями, но и его можно изловчиться и вытащить отдельно). Но вот проблема, нам нужно нашу сущность преобразовать в массив, чтобы вернуть в виде JSON в неком API.

И при этом, самое главное - нам нужно сохранить всю структуру! Т.е. мы не можем с помощью QueryBuilder сделать SQL запрос и вернуть этот массив, нам нужно именно объект преобразовать в массив. Сделать это можно с помощью symfony/serializer или руками (не смешно).

Из коробки Symfony 4 это не умеет (ну мы же микрофреймворк). Ок, ставим нужный пакет.

Но почему блин нельзя было сделать (и в других фреймворках этого нет) на основе рефлексии преобразование raw-data в json-data по схеме некого класса, не преобразовывая массив из бд в объект, а потом этот объект в JSON-схему.

Тут симфони снова ничем не лучше, так еще и решения из коробки нет. В итоге я пишу репозиторий, пишу Entity, пишу класс-енкодер, для преобразования Entity в массив и еще к этому всему прикручиваю версионирование. Это финиш.

В итоге у меня в чистой установке был микрофреймворк. Но я на него уже столько навесил стандартных пакетов (serializer, orm-pack, security...), что это уже не микрофреймворк ни разу. Это монстр.

Далее. Почему IS_AUTHENTICATED_FULLY и прочее нельзя было сделать константами? КАК?! Т.е. у меня реально в экшине есть вот такой код:

$this->isGranted('IS_AUTHENTICATED_FULLY')...

Вот он right-way? Объект Security нельзя было в метод передать и писать что-то вида:

public function someAction(Security $security)
{
    if ($security->getUser()->isGuest() === true) ....
}

Я мог бы этот экшн закрыть по аннотациям, но мне нужно показывать разный материал, в зависимости от того, вошел пользователь в систему или нет.

И кстати, а знаете что вернет TokenStorageInterface getUser() если пользователь не вошел? Он вернет слово «anon.». Не пустой объект, реализующий интерфейс UserInterface, а именно слово «anon.».

И в контроллер-трейте их быдлокодеры наговнякали следующий код:

 protected function getUser()
    {
        if (!$this->container->has('security.token_storage')) {
            throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".');
        }

        if (null === $token = $this->container->get('security.token_storage')->getToken()) {
            return;
        }

        if (!\is_object($user = $token->getUser())) {
            // e.g. anonymous authentication
            return;
        }

        return $user;
    }

Т.е. если вы забыли где-то про это и написали:

$this->getUser()->getId();
то во время выполнения можете получить 500 Error. И если про это не знать, то ошибка уйдет в продакшн.

И $this->getUser() в контроллере вернет null, а TokenStorageInterface getToken() getUser() вернет anon.

Ну и комментарии КЭПа в коде symfony:

    /**
     * Sets the token attributes.
     *
     * @param array $attributes The token attributes
     */
    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
    }

    /**
     * Returns an attribute value.
     *
     * @param string $name The attribute name
     *
     * @return mixed The attribute value
     *
     * @throws \InvalidArgumentException When attribute doesn't exist for this token
     */
    public function getAttribute($name)
    {
        if (!array_key_exists($name, $this->attributes)) {
            throw new \InvalidArgumentException(sprintf('This token has no "%s" attribute.', $name));
        }

        return $this->attributes[$name];
    }

/**
     * Sets an attribute.
     *
     * @param string $name  The attribute name
     * @param mixed  $value The attribute value
     */
    public function setAttribute($name, $value)
    {
        $this->attributes[$name] = $value;
    }

А где комментарий в стиле «кеп» написать нельзя - их тупо нет.

Вообще, у меня есть претензии к коду симфони. Комментариев нет, везде if if if if.. все на if'ах.

Я бы попросил знающих людей объяснить мне, почему так? Почему блин Symfony это круто и энтерпрайзно, а внутри все так плохо?

fman2
() автор топика
Ответ на: комментарий от fman2

забыли где-то про это и написали
$this->getUser()->getId();

А ты что, не проверяешь что возвращает getUser() ? А потому все и говорят, что кто на пыхе пишет, тот обезьяна.

все на if'ах

ИИ же!

не преобразовывая массив из бд в объект, а потом этот объект в JSON-схему

json_encode(['a' => 1, 'b' => 2]); в чем проблема то?

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

в нормально написанных системах getObject() вернет или заполненный объект или пустой. Но никак не null или строку.

https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistak...

Но даже если и возвращает null, почему в одном месте он вернет null, а в другом строку anon.?

fman2
() автор топика
Ответ на: комментарий от deep-purple

json_encode(['a' => 1, 'b' => 2]); в чем проблема то?

мы говорим о серьезном программировании, с репозиториями, сущностями и всем прочим.

Я бы мог вернуть из бд массив и преобразовать его в JSON. но у меня жесткая структура объектов и нужно получить массив по структуре объекта.

fman2
() автор топика
Ответ на: комментарий от fman2

Напиши свой метод поверх этого говна, обращайся к своему. Оставь вопросы «кто виноват», все претензии оформляй в иссуйки к авторам — а тут ты лишь поныть можешь как сложна жыть.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

а тут ты лишь поныть можешь как сложна жыть.

ну мне вполне этого хватит:)

fman2
() автор топика
Ответ на: комментарий от fman2

о серьезном программировании, с репозиториями, сущностями и всем прочим

С чего ты взял что это критерий серьезности и сложности продукта?

deep-purple ★★★★★
()
Ответ на: комментарий от fman2

Наследование в 3-5 уровней это не нарушение. Тем более если сделано всё с умом. В плюсах вот есть множественное наследование и одноименные методы с разными аргументами в одном классе. В пыхе твоя лазанья — это достижение той же цели доступными способами.

deep-purple ★★★★★
()
Ответ на: комментарий от fman2

мы говорим о серьезном программировании...

«Серьёзное программирование» и «autowire: true, autoconfigure: true» - две большие разницы, но ты их не видишь и ноешь на последнее, какого фига в нём так много магии. Проблема чисто в тебе. Symfony тебе предлагает выбор - или быстрое тяп ляп, но со встроенной магией (а как иначе!), или чуть медленнее, но чисто по своим правилам. А ты только один путь замечаешь... В общем, фигово ты Symfony знаешь.

anonymous
()
Ответ на: комментарий от anonymous

Symfony тебе предлагает выбор - или быстрое тяп ляп, но со встроенной магией (а как иначе!),

Это точно не к Symfony.

fman2
() автор топика
Ответ на: комментарий от fman2

Я с ней работаю несколько лет. Делал как скорое «тяп ляп» для простеньких, так и нормалайзеры, контроллеры, сборку компонентов через конфигурацию / компайлер пассы для огромных проектов. Так вот, в первом случае реализация магии - вторично, и я ею особо не интересовался, так как проекты были «совсем не об этом», а во втором случае такие удобные вещи, как ControllerTrait.php или там аннотации в контроллерах на фиг не сдались. :)

anonymous
()
Ответ на: комментарий от anonymous

Вот кстати этот ControllerTrait и нужно было выносить в отдельный пакет и устанавливать через Symfony Flex.

Я даже название придумал: symfony/like-lavarel

fman2
() автор топика
Ответ на: комментарий от fman2

Вот кстати этот ControllerTrait и нужно было выносить в отдельный пакет и устанавливать через Symfony Flex.

Ну, в остальных фреймворков удобные заготовки контроллеров тоже сразу из коробки идёт. :) Для простых вещей они самое то, наиболее востребованные.

anonymous
()
Ответ на: комментарий от anonymous

Ну я к тому и говорю) В Yii2 идет все это дело из коробки, но они честно говорят - мы за быструю разработку, вжик вжик и готово.

Laravel - для веб-ремесленников. Все на фасадах, вжик и также готово. Написал и забыл.

У Symfony другой подход, он за правильную разработку. $this->getUser() == null в контроллере не похоже на правильную разработку.

Если бы нужен был бы пользователь в экшене - его нужно было в этот экшн передать.

fman2
() автор топика

Просто другие фреймворки сделаны, чтобы с ними было удобно работать, а Symfony - чтобы всё было как в умных книжках. Последний раз я трогал симфони, когда была версия 2.8, не знаю, насколько сейчас все лучше, но думаю, что принципиально ничего не поменялось. Вот уже «тру» программисты Symfony, пишут, что autowiring и autoconfigure - это для говнокодеров, лол.

На Php Symfony был мой первый фреймворк, и работал я с ним достаточно. Тоже думал, что это самый правильный фреймворк. Но потом, попробовав Yii, понял, что Symfony лучше выкинуть на помойку. Это просто небо и земля, настолько в Symfony всё было неудобно.

Возвращаться к проекту на Symfony - это тоже боль. Все эти конфиги, аннотации, как создать helper в twig, как создать свой тип поля в формах и прочие козьи тропы - всё это выветривается из головы моментально, если постоянно не писать на Symfony. Ни с одним другим фреймворком или языком это так сильно не было выражено.

nguseff
()
Ответ на: комментарий от fman2

В Symfony наши сущности чистые (не считая хлама с аннотациями, но и его можно изловчиться и вытащить отдельно). Но вот проблема, нам нужно нашу сущность преобразовать в массив, чтобы вернуть в виде JSON в неком API.

А как насчет объект вернуть? Я наоборот не понимаю подход Yii с постоянным return array.

bitfroster ★★
()
Последнее исправление: bitfroster (всего исправлений: 1)
Ответ на: комментарий от bitfroster

А как насчет объект вернуть? Я наоборот не понимаю подход Yii с постоянным return array.

Как вы в JSON вернете объект? У меня фронт на Vue.

fman2
() автор топика
Ответ на: комментарий от bitfroster

Ясно, понятно.

Если что-то будет непонятно, дайте знать.

fman2
() автор топика
Ответ на: комментарий от fman2

Как вы в JSON вернете объект?

Есть такая вещь, как Serializer. Как раз для таких случаев.

Если что-то будет непонятно, дайте знать.

Обязательно.

bitfroster ★★
()
Последнее исправление: bitfroster (всего исправлений: 1)
Ответ на: комментарий от bitfroster

Этого нет из коробки. Снова ставить отдельный пакет:) Да и рефлексией можно было без преобразований разрулить

fman2
() автор топика
Ответ на: комментарий от anonymous

Давайте не будем скатываться. PHP свои цели выполняет.

fman2
() автор топика

Двигаемся дальше. Аутентификация пользователя с рекапчей это отдельная песня.

У нас нет методов onBeforeAuthentificate(Request $request) и onAfterAuthentificate(UserInterface $user), но это ладно. Куда вставлять проверку на каптчу я додумался.

Далее, почему у $request нет методов: isGet(), isPost(), isPut() и так далее?

Что это за такое:

$request->getMethod() == 'POST'
$request->isMethod('POST');

Ну можно же писать:

$request->isPost() и все станет понятно.

А получение данных:

$request->request->get('data');
Мы получаем GET или POST?

Я за пару дней, сидя по 2-3 часа и делая все по symfony-way дальше формы входа и регистрации не двинулся. Это не считая настроенного webpack, но там все очень быстро.

fman2
() автор топика
11 декабря 2018 г.
Ответ на: комментарий от fman2

Но никак не null или строку

nullable это какбы фича. Даже тайпхинт для этого запилили. Но уж если на то пошло, то по твоей логике и getToken не должен возвращать null, а какой-то аноновский псевдотокен. И тогда, внезапно, приведённый код получается корректный и getUser вернёт анон инстанс юзера созданный по анон-псевдотокену. Ну и кто тут мартыхан, может ты?

no-such-file ★★★★★
()
5 марта 2019 г.

fman2, no-such-file вопрос немного не по теме, есть ли в symfony хотя бы какой-то аналог rails console или laravel tinker, чтобы можно было из коносли работать с базой данных?

anonymous
()
Ответ на: комментарий от anonymous

Не знаю, вряд ли, чтобы это было.

fman2
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.