Symfony 4 - Как добавить бизнес-логику в сущность - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть сущность Article , и фактически я использую функцию path () в 3 шаблонах веток, предоставляя в качестве второго параметра slug статьи, чтобы получить отображаемый URLодна статья.

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

Я думал использовать метод getUrl () в классе Article, но я не могу использовать службу Route для генерации URL.

Есть ли лучший способ сделать это?что в Symfony 4?

Это часть ArticleController :

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;

use App\Entity\Article;
use App\Repository\ArticleRepository;

class ArticleController extends AbstractController
{
    ...

    /**
     * @Route("/article/{slug}", name="article_show")
     */
    public function show(Article $article) {
        return $this->render('article/show.html.twig', [
            'article' => $article
        ]);
    }

}

Тогда в шаблонах у меня есть подобный код, подобный этому:

 {% for article in articles %}
    ...

        <a href="{{ path('article_show',{ 'slug': article.slug } ) }}">
            {{ article.title }}
        </a>
    ...
 {% endfor %}

Я хотел бы иметь такой код:

 {% for article in articles %}
    ...

        <a href="{{ article.getUrl() }}">
            {{ article.title }}
        </a>
    ...
 {% endfor %}

, где getUrl выполняет работу метода path (), поэтому, если я что-то изменю в маршруте,будет отражено во всех шаблонах, но я не могу сделать это, потому что я не могу получить маршрутОшибка в объекте Article.

Так есть ли альтернативный способ достижения той же цели?

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Я не могу понять, почему бизнес-объект должен знать о системе маршрутизации.

Если вы хотите, чтобы объект знал его URL-адрес, просто добавьте метод setUrl() и getUrl() в свой объекти сохранить его уже сгенерированный URL

0 голосов
/ 08 февраля 2019

То, что вы ищете, является неправильным способом достижения желаемого эффекта.Чтобы это работало, вам нужно внедрить маршрутизатор в сущность, которая, по сути, превращает его в «бизнес-логику» (например, контроллер), а не в «постоянство», и нарушает принцип единой ответственности.Кроме того, это сложно сделать технически, так как вам придется модифицировать внутренности Doctrine

. Есть два способа правильно это обработать, и оба они включают в себя собственное расширение Twig:

Самый простой способ - определитьпользовательский фильтр Twig, который заботится о генерации правильного URL:

<?php

namespace App\Twig\Extension;

use App\Entity\Article;

use Symfony\Component\Routing\RouterInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;

class ArticleExtension extends AbstractExtension
{
    private $router;

    public function __construct(RouterInterface $router)
    {
        $this->router = $router;
    }

    public function getFilters()
    {
        return [
            new TwigFilter('article_url', [$this, 'getArticleUrl']),
        ];
    }

    public function getArticleUrl(Article $article): string
    {
        return $this->router->generate('article_show', ['slug' => $article->getSlug()]);
    }
}

Затем в ветке вы просто используете фильтр следующим образом:

{% for article in articles %}
    ...

    <a href="{{ article|article_url }}">
        {{ article.title }}
    </a>
    ...
{% endfor %}

Если вы используете Symfony 3.4+ сДля создания awtowiring / autoconfigure достаточно создать класс, в противном случае вам необходимо зарегистрировать его как расширение ветки в контейнере.Пожалуйста, обратитесь к документации Symfony для получения более подробной информации

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

...