Как строишь приложения на Symfony2 ты?

Всегда была очень интересна эта тема, давайте делиться опытом!
Например, как вы организовываете тонкие контроллеры при разработке обычных сайтов?
, как вы организовываете тонкие контроллеры при разработке REST API сайтов?
,какой структуры проектов придерживаетесь?
,какие "лайфхаки" можете посоветовать?

В моем случае при построении REST API на Symfony2 я использую JMSSerializer, FOSRest, NelmioApi. В контроллерах все Action у меня идут одной строкой (пример return $this->managerEntity->action(Entity $entity); ) В Action я никогда не принимаю параметр Request $request, т.к обычно в аннотациях получаю все нужные мне данные и заполняю ими объект. Делаю это с помощью ParamConverter, QueryParam. Такой подход на мой взгляд дает более четко понимание того, с чем придется работать. По поводу менеджеров (пример кода выше), у меня они занимаются редиректом на сервис ( иногда еще упаковкой данных в нужные форматы) т.е получают данные с контроллера и вызывает нужные сервисы/репозитории для управление или сохранения данных. Таким образом я получаю удобный для меня уровень абстракции, очень тонкие методы и вполне читаемый код (иногда правда аннотации разрастаются). Так же при разработке REST API я вообще не использую формы, данные валидируются встроенным валидатором от Symfony +правилами описаными в самой сущности

В случае построения "обычных" сайтов т.е с рендером твига и прочим, стараюсь в контроллере оставлять только handle для формы, но и от него ищу всяческие способы избавиться.

P.S best practices читал, бандлы популярные смотрел, но даже в них очень часто код выглядят не самым приятным образом и иногда создается впечатление, что вся красота ооп иногда проходит мимо php
P.S vol. 2 если есть ссылки на проекты на git'е написаны (по вашему мнению) в хорошем стиле, было бы круто выложить их сюда


Добавлено 9.2.15
----------------------------------------------------
Сюда буду добавлять примеры "хорошо" написанных бандлов/сайтов на Symfony2, что бы можно было брать как пример

https://github.com/orocrm/platform

Добавлено 12.2.15
E-commerce solution build on top of symfony
https://github.com/elcodi/elcodi
  • Вопрос задан
  • 4962 просмотра
Пригласить эксперта
Ответы на вопрос 4
bboytiwst
@bboytiwst Автор вопроса
Ну раз никто ничего интересного не пишет, напишу сам :) Может решение и достаточно очевидное, но постоянно вижу дубли кода для загрузки файлов в Symfony2 когда не требуется что то комплексное как Gaufrette или же Doctrine Uploadable, можно использовать трейты.

src/Traits/UploadTrait.php

<?php


namespace YouBundle\Traits;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;

trait UploadTrait {

    /**
     * @Assert\File(
     * maxSize="2M",
     * mimeTypes={
     *     "image/png",
     *     "image/jpeg",
     *     "image/gif",
     *     "image/jpg"
     * }
     * )
     *
     */
    private $file;

    private $temp;

    /**
     * @return mixed
     */
    public function getFile()
    {
        return $this->file;
    }
    /**
     * Sets file.
     *
     * @param UploadedFile $file
     */
    public function setFile(UploadedFile $file = null)
    {
        $this->file = $file;

        if (isset($this->path)) {
            $this->temp = $this->path;
            $this->path = null;
        } else {
            $this->path = 'initial';
        }
    }

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function preUpload()
    {

        if (null !== $this->getFile()) {

            $filename = sha1(uniqid(mt_rand(), true));
            $this->path = $filename.'.'.$this->getFile()->guessExtension();
        }
    }

    /**
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     */
    public function upload()
    {
        if (null === $this->getFile()) {
            return;
        }

        $this->getFile()->move($this->getUploadRootDir(), $this->path);


        if (isset($this->temp)) {

            unlink($this->getUploadRootDir().'/'.$this->temp);

            $this->temp = null;

        }
        $this->file = null;
    }

    public function getAbsolutePath()
    {
        return null === $this->path
            ? null
            : $this->getUploadRootDir().'/'.$this->path;
    }

    public function getWebPath()
    {
        return null === $this->path
            ? null
            : $this->getUploadDir().'/'.$this->path;
    }

    protected function getUploadRootDir()
    {
        return __DIR__.'/../../../../web/'.$this->getUploadDir();
    }
}


а в самой сущности надо задать свойство $path
/**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $path;


и определить папку в которую заливать это все добро будем
protected function getUploadDir()
    {
        return 'images/courts/photos';
    }


P.S решение предоставляю как базовое, не претендующее на что то серьезное, код взят с официальной документации и просто завернут в трейт, который можно использовать повторно. Если будет надобность на проекте в усовершенствовании, то допилю и выложу сюда еще и обновленную версию
Ответ написан
slimus
@slimus
Symfony, Golang
По поводу тонких контроллеров. Разбирался в одном проекте, было около 50 сервисов написанных для него. Контроллеры получились тоже примерно однострочные, но вся логика в сервисах была адово запутана. Но разобраться в таком коде можно, и мне потребовалось всего пара часов чтобы я понимал именование сервисов и файлов.
Поделитесь опытом как Вы строите запросы для апи где есть сортировка+постраничник+множество фильтров? Какую логику куда выносите? Как выглядят репозитории?
Спасибо!
Ответ написан
@ta1isman
Ответ написан
Комментировать
@GrizliK1988
В команде для реализации тонких контроллеров мы используем дополнительную прослойку BusinessCase, которая дергает сервисы для получения нужных данных и отдает их котроллеру в готовом для преобразования в Respone виде.

Так же хочу отметить, что JMSSerializer очень медленный из-за используемой внутри него рефлексии. Поэтому мы используем собственное решение (которое пока не выложено в opensource).
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы