Ergebnis 1 bis 10 von 10

Thema: Ajax und Contao Framework initialisieren

  1. #1
    Contao-Nutzer
    Registriert seit
    17.11.2016.
    Beiträge
    25

    Frage Ajax und Contao Framework initialisieren

    Hallo zusammen,

    ich bin seit ein paar Wochen dabei, alle meine Contao 4 Erweiterungen in 5er Bundles umzuschreiben. Bei den meisten hat das zum Glück recht gut funktioniert, nun hänge ich aber schon seit Tagen an einem eigentlich simplen Problem: Eine Ajax-Ausgabe von Produkten auf einem Merkzettel, die im Local Storage gespeichert sind.

    Dazu habe ich einen NotepadController als Content Element angelegt, der das Template ausgibt. Beim Aufruf der Seite sollen nun per Ajax die vom Besucher ausgewählten Produkte geladen werden. Die Abfrage erfolgt auf die URL /_ajax/notepad, die ich in einem NotepadAjax Controller als Route definiert habe. Dabei werden die Produkt-IDs und das aktuelle Token mit übergeben.

    Mein Problem ist aktuell, dass ich dabei das Contao Framework nicht korrekt initialisiert bekomme.

    Hier erst mal mein Code:

    Code:
    # config/services.yaml
    services:
        _defaults:
            autowire: true
            autoconfigure: true
    
        App\ContaoProductsBundle\:
            resource: ../src/
            exclude: ../src/{Cron,DependencyInjection,Model,Session}
    
        App\ContaoProductsBundle\Controller\NotepadAjax:
            public: true
            arguments:
                - '@contao.framework'
                - '@database_connection'
                - '@contao.csrf.token_manager'
                - '%contao.csrf_token_name%'
            tags:
                - controller.service_arguments
    PHP-Code:
    # src/Controller/NotepadAjax.php

    namespace App\ContaoProductsBundle\Controller;

    use 
    App\ContaoProductsBundle\Model\ProductsModel;
    use 
    App\ContaoProductsBundle\Controller\ContentElement\NotepadController;
    use 
    Contao\CoreBundle\Csrf\ContaoCsrfTokenManager;
    use 
    Contao\CoreBundle\Framework\ContaoFramework;
    use 
    Contao\FilesModel;
    use 
    Contao\Input;
    use 
    Contao\StringUtil;
    use 
    Contao\System;
    use 
    Doctrine\DBAL\Connection;
    use 
    Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use 
    Symfony\Component\HttpFoundation\Response;
    use 
    Symfony\Component\HttpFoundation\Request;
    use 
    Symfony\Component\Routing\Annotation\Route;
    use 
    Symfony\Component\Security\Csrf\CsrfToken;

    class 
    NotepadAjax extends AbstractController
    {
        public function 
    __construct(
            private 
    readonly ContaoFramework $framework,
            private 
    readonly Connection $connection,
            private 
    readonly ContaoCsrfTokenManager $tokenManager,
            private 
    readonly string $csrfTokenName,
        ) {
        }

        
    #[Route('/_ajax/notepad', name: 'app_contao_products_ajax_notepad', defaults: ['_token_check' => true])]
        
    public function notepadajax(Request $request): Response
        
    {
            if (!isset(
    $_POST['token']))
            {
                return new 
    Response('');
            }

            
    // Token prüfen
            
    $isTokenValid $this->tokenManager->isTokenValid(new CsrfToken($this->csrfTokenName$_POST['token']));

            if (!
    $isTokenValid || $_SERVER['REQUEST_METHOD'] != 'POST' || !$request->isXmlHttpRequest())
            {
                return new 
    Response('');
            }
    ... 
    Erst hatte ich versucht, weitere Daten aus dem NotepadController zu holen:
    PHP-Code:
        $notepad = new NotepadController();
        
    $return $notepad->getNotepadData();
        return new 
    Response($return); 
    Hierbei kommt aber die Fehlermeldung:
    The Symfony container is not available, did you initialize the Contao framework?

    Bei Verwendung eines Models, kommt folgende Fehlermeldung:
    There is no class for table "tl_files" registered in $GLOBALS['TL_MODELS']

    Bei Verwendung von $rootDir = System::getContainer()->getParameter('kernel.project_dir'); gibt das System
    Call to a member function getParameter() on null aus.

    Versuche ich das Framework mit $this->framework->initialize(); zu initialisieren, kommt:
    The "security.csrf.token_manager" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.

    Einfach Datenbankabfragen per $objData = $this->connection->executeQuery("SELECT * FROM..."); funktionieren hingegen.

    Wo liegt mein Fehler oder gibt es eine andere Möglichkeit, das umzusetzen? Vielleicht auch gleich direkt im NotepadController, von dem ich eh noch weitere Daten benötige.
    Ich bin für jeden Tipp dankbar!

    Gruß Tim

  2. #2
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.125
    Partner-ID
    10107

    Standard

    Nutze den Debug-Modus und poste den Stack Trace.

    Übrigens, du solltest nicht auf $_POST direkt zugreifen. Du hast ja bereits das Request Objekt in deinem Controller verfügbar.
    » sponsor me via GitHub or PayPal or Revolut

  3. #3
    Contao-Nutzer
    Registriert seit
    17.11.2016.
    Beiträge
    25

    Standard

    Danke für die schnelle Antwort!

    Übrigens, du solltest nicht auf $_POST direkt zugreifen. Du hast ja bereits das Request Objekt in deinem Controller verfügbar.
    Habe ich gleich getauscht!

    Hier mal zwei Stack Traces.

    Bei Verwendung von $this->framework->initialize();:

    Code:
    Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException:
    The "security.csrf.token_manager" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.
    
      at C:\UwAmp\www\contao5\vendor\symfony\dependency-injection\Container.php:249
      at Symfony\Component\DependencyInjection\Container::make()
         (C:\UwAmp\www\contao5\vendor\symfony\dependency-injection\Container.php:211)
      at Symfony\Component\DependencyInjection\Container->get()
         (C:\UwAmp\www\contao5\vendor\heimrichhannot\contao-ajax-bundle\src\Manager\AjaxManager.php:219)
      at HeimrichHannot\AjaxBundle\Manager\AjaxManager->setRequestTokenExpired()
         (C:\UwAmp\www\contao5\vendor\heimrichhannot\contao-ajax-bundle\src\EventListener\Contao\InitializeSystemListener.php:57)
      at HeimrichHannot\AjaxBundle\EventListener\Contao\InitializeSystemListener->__invoke()
         (C:\UwAmp\www\contao5\vendor\contao\core-bundle\src\Framework\ContaoFramework.php:217)
      at Contao\CoreBundle\Framework\ContaoFramework->triggerInitializeSystemHook()
         (C:\UwAmp\www\contao5\vendor\contao\core-bundle\src\Framework\ContaoFramework.php:168)
      at Contao\CoreBundle\Framework\ContaoFramework->initializeFramework()
         (C:\UwAmp\www\contao5\vendor\contao\core-bundle\src\Framework\ContaoFramework.php:93)
      at Contao\CoreBundle\Framework\ContaoFramework->initialize()
         (C:\UwAmp\www\contao5\vendor\app\contao-products-bundle\src\Controller\NotepadAjax.php:50)
      at App\ContaoProductsBundle\Controller\NotepadAjax->notepadajax()
         (C:\UwAmp\www\contao5\vendor\symfony\http-kernel\HttpKernel.php:181)
      at Symfony\Component\HttpKernel\HttpKernel->handleRaw()
         (C:\UwAmp\www\contao5\vendor\symfony\http-kernel\HttpKernel.php:76)
      at Symfony\Component\HttpKernel\HttpKernel->handle()
         (C:\UwAmp\www\contao5\vendor\symfony\http-kernel\Kernel.php:197)
      at Symfony\Component\HttpKernel\Kernel->handle()
         (C:\UwAmp\www\contao5\public\index.php:44)
    Bei Aufruf von
    $notepad = new NotepadController();
    $return = $notepad->getNotepadData();:

    Code:
    RuntimeException:
    The Symfony container is not available, did you initialize the Contao framework?
    
      at C:\UwAmp\www\contao5\vendor\contao\core-bundle\contao\library\Contao\System.php:143
      at Contao\System->import()
         (C:\UwAmp\www\contao5\vendor\contao\core-bundle\contao\library\Contao\System.php:97)
      at Contao\System->__construct()
         (C:\UwAmp\www\contao5\vendor\contao\core-bundle\contao\library\Contao\DcaExtractor.php:99)
      at Contao\DcaExtractor->__construct()
         (C:\UwAmp\www\contao5\vendor\contao\core-bundle\contao\library\Contao\DcaExtractor.php:134)
      at Contao\DcaExtractor::getInstance()
         (C:\UwAmp\www\contao5\vendor\contao\core-bundle\contao\library\Contao\Model.php:284)
      at Contao\Model::getUniqueFields()
         (C:\UwAmp\www\contao5\vendor\contao\core-bundle\contao\library\Contao\Model.php:1030)
      at Contao\Model::findBy()
         (C:\UwAmp\www\contao5\vendor\app\contao-products-bundle\src\Model\ProductsModel.php:259)
      at App\ContaoProductsBundle\Model\ProductsModel::findPublishedById()
         (C:\UwAmp\www\contao5\vendor\app\contao-products-bundle\src\Controller\ContentElement\NotepadController.php:95)
      at App\ContaoProductsBundle\Controller\ContentElement\NotepadController->getNotepadData()
         (C:\UwAmp\www\contao5\vendor\app\contao-products-bundle\src\Controller\NotepadAjax.php:54)
      at App\ContaoProductsBundle\Controller\NotepadAjax->notepadajax()
         (C:\UwAmp\www\contao5\vendor\symfony\http-kernel\HttpKernel.php:181)
      at Symfony\Component\HttpKernel\HttpKernel->handleRaw()
         (C:\UwAmp\www\contao5\vendor\symfony\http-kernel\HttpKernel.php:76)
      at Symfony\Component\HttpKernel\HttpKernel->handle()
         (C:\UwAmp\www\contao5\vendor\symfony\http-kernel\Kernel.php:197)
      at Symfony\Component\HttpKernel\Kernel->handle()
         (C:\UwAmp\www\contao5\public\index.php:44)

  4. #4
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.125
    Partner-ID
    10107

    Standard

    Zitat Zitat von Silent-Bob Beitrag anzeigen
    Hier mal zwei Stack Traces.

    Bei Verwendung von $this->framework->initialize();:

    Code:
    Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException:
    The "security.csrf.token_manager" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.
    
      at C:\UwAmp\www\contao5\vendor\symfony\dependency-injection\Container.php:249
      at Symfony\Component\DependencyInjection\Container::make()
         (C:\UwAmp\www\contao5\vendor\symfony\dependency-injection\Container.php:211)
      at Symfony\Component\DependencyInjection\Container->get()
         (C:\UwAmp\www\contao5\vendor\heimrichhannot\contao-ajax-bundle\src\Manager\AjaxManager.php:219)
      at HeimrichHannot\AjaxBundle\Manager\AjaxManager->setRequestTokenExpired()
         (C:\UwAmp\www\contao5\vendor\heimrichhannot\contao-ajax-bundle\src\EventListener\Contao\InitializeSystemListener.php:57)
      at HeimrichHannot\AjaxBundle\EventListener\Contao\InitializeSystemListener->__invoke()
         (C:\UwAmp\www\contao5\vendor\contao\core-bundle\src\Framework\ContaoFramework.php:217)
      at Contao\CoreBundle\Framework\ContaoFramework->triggerInitializeSystemHook()
         (C:\UwAmp\www\contao5\vendor\contao\core-bundle\src\Framework\ContaoFramework.php:168)
      at Contao\CoreBundle\Framework\ContaoFramework->initializeFramework()
         (C:\UwAmp\www\contao5\vendor\contao\core-bundle\src\Framework\ContaoFramework.php:93)
      at Contao\CoreBundle\Framework\ContaoFramework->initialize()
         (C:\UwAmp\www\contao5\vendor\app\contao-products-bundle\src\Controller\NotepadAjax.php:50)
      at App\ContaoProductsBundle\Controller\NotepadAjax->notepadajax()
         (C:\UwAmp\www\contao5\vendor\symfony\http-kernel\HttpKernel.php:181)
      at Symfony\Component\HttpKernel\HttpKernel->handleRaw()
         (C:\UwAmp\www\contao5\vendor\symfony\http-kernel\HttpKernel.php:76)
      at Symfony\Component\HttpKernel\HttpKernel->handle()
         (C:\UwAmp\www\contao5\vendor\symfony\http-kernel\Kernel.php:197)
      at Symfony\Component\HttpKernel\Kernel->handle()
         (C:\UwAmp\www\contao5\public\index.php:44)
    Das ist ein Fehler in heimrichhannot\contao-ajax-bundle

    Wurde vor kurzem dort behoben, laut Slack. Führe eine komplette Paketaktualisierung durch.
    » sponsor me via GitHub or PayPal or Revolut

  5. #5
    Contao-Nutzer
    Registriert seit
    17.11.2016.
    Beiträge
    25

    Standard

    Super, Danke für die Info. Nun ist der Fehler behoben!!!

    Könntest du mir vielleicht noch einen Tipp geben, wie ich auf die Daten aus dem NotepadController zugreifen kann? Das Content Element ruft standardmäßig die Funktion getResponse() auf:

    PHP-Code:
    #[AsContentElement('notepad', category: 'includes')]
    class NotepadController extends AbstractContentElementController
    {
        protected function 
    getResponse(Template $templateContentModel $modelRequest $request): Response

    Aus $model bräuchte ich aber noch einige Informationen, die ich nicht unbedingt per Ajax übergeben möchte.

  6. #6
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.125
    Partner-ID
    10107

    Standard

    NotepadController ist ja ein eigenes Inhaltselement. Der Request für das NotepadController Inhaltselement und für deinen NotepadAjax Controller sind ja völlig unterschiedlich. Insofern kannst du nicht "auf die Daten des NotepadControllers" zugreifen. Du musst alles an deinen AJAX Controller übergeben, was dort benötigt wird. Du könntest bspw. die ID des Content Elements übergeben, damit du dort dann wieder die Daten des Content Elements aus der Datenbank laden lassen kannst (da solltest du aber auch eine Prüfung einbauen, dass die übergebene ID die ID eines NotepadController Content Elements ist bspw.).
    » sponsor me via GitHub or PayPal or Revolut

  7. #7
    Contao-Nutzer
    Registriert seit
    17.11.2016.
    Beiträge
    25

    Standard

    Da hast du natürlich recht. Im alten Skript hatte ich den Ajax-Request direkt auf dieselbe URL geschickt und ihn ebenfalls im Content Element verarbeitet. Ich dachte, mit einer eigenen Route wäre es nun etwas eleganter. Letztendlich habe ich mein Script dahingehend umgeschrieben, dass ich es nun wieder genauso mache:

    PHP-Code:
    class NotepadController extends AbstractContentElementController
    {
        public function 
    __construct(
            private 
    readonly ContaoFramework $framework,
            private 
    readonly Connection $connection,
        ) {
        }

        protected function 
    getResponse(Template $templateContentModel $modelRequest $request): Response
        
    {
            
    // Ajax-Request
            
    if ($_SERVER['REQUEST_METHOD'] == 'POST' && $request->isXmlHttpRequest())
            {
                
    // Token prüfen
                
    $strToken $request->get('token');

                if (!isset(
    $strToken))
                {
                    exit;
                }

                
    $container System::getContainer();
                
    $isTokenValid $container->get('contao.csrf.token_manager')->isTokenValid(new CsrfToken($container->getParameter('contao.csrf_token_name'), $strToken));

                if (!
    $isTokenValid)
                {
                    exit;
                }

                
    // Daten holen und als JSON zurückgeben
                
    $this->getNotepadData($model$request);
                exit;
            }
    ... 
    Die Lösung mit exit ist zwar nicht schön, funktioniert aber.
    Hab auf jeden Fall vielen Dank für deine Unterstützung!

  8. #8
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.125
    Partner-ID
    10107

    Standard

    Du solltest $request->getMethod() nutzen, und nicht direkt auf $_SERVER zugreifen
    » sponsor me via GitHub or PayPal or Revolut

  9. #9
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.125
    Partner-ID
    10107

    Standard

    Und statt exit; kannst du
    PHP-Code:
    throw new ResponseException(new JsonResponse($data)); 
    nutzen.
    » sponsor me via GitHub or PayPal or Revolut

  10. #10
    Contao-Nutzer
    Registriert seit
    17.11.2016.
    Beiträge
    25

    Standard

    Sehr schön, dann wird das Ganze ja doch noch rund!

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Lesezeichen

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •