Symfony - sdílení "bloků" napříč aplikací rubrika: Programování: PHP

4 skocdopolet
položil/-a 17.5.2015

Ahoj všem,

chtěl bych zde požádat o pomoc se Symfony frameworkem na který bych rád přešel z programování v čistém PHP. Prvotní znalosti o frameworku jsem čerpal z materiálů na stránkách (The Book), většina z popisovaných částí mi je vcelku jasná. Začal jsem tedy tvořit první aplikaci a při tom jsem narazil na následující problém, o němž nedokážu ani vygooglit, jak jej vyřešit. Možná jdu na to nějak celkově špatně...

Celkem hezky se to dá popsat například na aplikaci blogu. Dejme tomu že mám definovány controllery například indexAction (výpis článků) a showAction(id) (článek). Web používá layout, kde je postranní sidebar. Pokud bych například chtěl do sidebaru vložit výpis nejčtenějších článků, nevím, jakým způsobem se to má správně udělat, abych jej měl zobrazem v obou controllerech.

Napadají mě následující řešení:
1) Přidat do každého controlleru i data pro rendrování postranního panelu
Tak bych to asi vyřešil, ale připadá mi to poněkud neohrabané
2) Twig má metodu render, kde se určí controller a případné argumenty
Možná to je ta správná cesta, ovšem nevím, zda bych musel danou metodu controlleru například naroutovat i na URL. V případě nejčtenějších článků by to asi ani nevadilo mít například url /nejctenejsi, ale jsou případy kdy to není třeba
3) Nějakým různým děděním tříd
Teď vůbec nevím jak bych to dělal.

Díky moc předem za rady
Tomáš Skočdopole

Komentáře

  • Tomáš Votruba : Zajímalo by mě, jak k tomu přistupuješ teď s odstupem? Hledám něco podobného, ale nedává my smysl se vázat na Controller (a na vše, na co se váže on). 8.1.2016
odkaz Vyřešeno
2 cydreb
odpověděl/-a 21.5.2015
 
upravil/-a 21.5.2015

Dá sa to riešiť napríklad takto.

1.) Include v Twig

{{ include('AppBundle:Admin/Layout:articles.html.twig', {'articles': articles, 'max': max}) }}

Dáta articles a max by bolo potrebné predávať includovanému twig súboru v každom twigu v ktorom by sa include daného súboru použil => pre príklad s článkami to nie je príliš vhodné riešenie, v iných prípadoch sa však často hodí, napr. tu:

{% for article in articles %}
    {{ include('AppBundle:Admin/Layout:article.html.twig', {'article': article}) }}
{% endfor %}

2.) Render v Twig

{{ render(controller('AppBundle:Admin/Layout:articles')) }}

Dáta articles a max by vracala metóda articlesAction triedy LayoutCotroller do ktorej by sa mali dostať cez service, napr. takto:

function articlesAction(){
    // ... 
    return ['articles' => $this->get('article')->getMostRead($max)];
}

3.) Twig Extension

Bolo by potrebné vytvoriť Twig Extension a tú nakonfigurovať v services.yml ako service. V services.yml by bolo tiež potrebné nakonfigurovať príslušný repozitár ako service a predať ho danej Twig Extension pomocou constructor injection.

Súbor services.yml:

repository.article:
      class: App\Bundle\Entity\ArticleRepository
      factory_service: doctrine.orm.default_entity_manager
      factory_method: getRepository
      arguments:
          - App\Bundle\Entity\Article
 
twig.article:
      class: App\Bundle\Twig\Extension\ArticleExtension
      arguments:
          articleRepository: @repository.article
      tags:
          - { name: twig.extension }

Súbor ArticleExtension.php:

class ArticleExtension extends \TwigExtension {
    private $articleRepository;
 
    public function __construct(ArticleRepository $articleRepository){
        $this->articleRepository = $articleRepository;
    }
 
    public function mostReadFunction(){
        // ...
        $articles = $this->articleRepository->getMostRead($max);
        // ...
    }
 
    // ...
}

Súbor *.html.twig:

{{ most_read_articles() }}

V prípade príkladu s blogom by som to riešil pravdepodobne tak ako v bode 2.) v kombinácii s bodom 1.). Z bodu 1.) mám na mysli časť {% for article in articles %} ... {% endfor %}

Pro zobrazení všech 9 odpovědí se prosím přihlaste:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.