Ich schreibe eine Erweiterung, die Kategorien, Produkte, Shops, Tags, etc. ausgeben soll. Dafür habe ich einen Page Controller und ein Frontend Modul geschrieben, wie du es in einem anderen Beitrag empfohlen hast. Die URLs sehen bspw. so aus:
/seite/produkt
/seite/kategorien
/seite/kategorien/kategorie1
/seite/kategorien/kategorie1/neuheiten
/seite/shops
/seite/shops/shop1
/seite/tags
/seite/tags/tag1
Der Page Controller nimmt die URL und analysiert die einzelnen Fragmente. Die übergibt er dann an die entsprechenden Klassen, die die gewünschten Daten holen und als geparstes Template zurückgeben. Das übergibt der Page Controller als Variable an den Request und rendert die Seite.
Das Frontend-Modul in der Seite holt sich schließlich diese Variable, packt die ins Module-Template und gibt den Response dann zurück.
Alles zu posten, würde den Rahmen sprengen. Hier mal ein Ausschnitt aus meinem Page Controller:
Code:
namespace Example\ContaoExampleBundle\Controller\Page;
use Contao\CoreBundle\DependencyInjection\Attribute\AsPage;
use Contao\CoreBundle\Exception\PageNotFoundException;
use Contao\Environment;
use Contao\FrontendIndex;
use Contao\ModuleModel;
use Contao\PageModel;
use Contao\System;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
#[AsPage(type: 'example_page', path: '{slugs}', requirements: ['slugs' => '.+'], defaults: ['slugs' => ''])]
class ExamplePageController
{
public function __invoke(Request $request, PageModel $pageModel, string $slugs): Response
{
$GLOBALS['TL_LANGUAGE'] = $request->getLocale();
System::loadLanguageFile('default');
// Slugs in Array aufteilen
$arrSlugs = explode('/', $slugs);
// Einstellungen des Frontend Modules holen (dort sind Bildgrößen festgelegt, die Anzahl Produkte pro Seite, etc.)
$moduleModel = ModuleModel::findOneByType('examplepage');
// Wenn keine Slugs, dann die Suche ausgeben
if ($slugs === '')
{
$search = new SearchController();
$response = $search->search($pageModel, $moduleModel);
}
// Kategorien ausgeben
elseif (substr($arrSlugs[0], 0, 6) === 'categories')
{
// Einzelne Kategorie ausgeben
if (isset($arrSlugs[1]) && preg_match('/^[a-z0-9\-]+$/', $arrSlugs[1]) === 1)
{
$categories = new CategoriesController();
$response = $categories->category($pageModel, $moduleModel, $arrSlugs);
}
// Übersicht aller Kategorien ausgeben
else
{
$categories = new CategoriesController();
$response = $categories->categories($pageModel, $moduleModel, $arrSlugs);
}
}
...
$request->attributes->set('output', $response);
return (new FrontendIndex())->renderPage($pageModel);
}
Und so sieht das Frontend Modul aus:
Code:
namespace Example\ContaoExampleBundle\Controller\FrontendModule;
use Contao\CoreBundle\Controller\FrontendModule\AbstractFrontendModuleController;
use Contao\CoreBundle\DependencyInjection\Attribute\AsFrontendModule;
use Contao\ModuleModel;
use Contao\PageModel;
use Contao\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
#[AsFrontendModule(type:'examplepage', category:'example', template:'mod_examplepage')]
class ExamplePageModuleController extends AbstractFrontendModuleController
{
public function __invoke(Request $request, ModuleModel $model, string $section, array $classes = null, PageModel $page = null): Response
{
return parent::__invoke($request, $model, $section, $classes);
}
protected function getResponse(Template $template, ModuleModel $model, Request $request): Response
{
$output = $request->attributes->get('output');
$template->output = $output;
return $template->getResponse();
}
}
Das Ganze steckt noch mitten in der Entwicklung, daher gibt es noch etliches zu verbessern. Ich bin aber froh, dass es bis hierhin schon mal funktioniert.