Contao-Camp 2024
Ergebnis 1 bis 8 von 8

Thema: Externes Skript durch Controller ersetzen

  1. #1
    Contao-Nutzer
    Registriert seit
    29.06.2020.
    Beiträge
    4

    Standard Externes Skript durch Controller ersetzen

    Hallo zusammen,

    ich habe leider generell noch keine Erfahrungen mit Contao, beschäftige mich aber gerade damit ein altes System auf eine neue Version zu aktualisieren. Das funktioniert soweit ganz gut, bis ich an die Stelle kam, an der externe PHP-Skripte in das System eingebunden werden sollen. In 4.9 schnappt sich durch die .htaccess Rewrite Regeln die index.php alle Skriptaufrufe, so dass bisherige extern liegende Skripte nicht mehr aufrufbar sind. Ich könnte jetzt natürlich einfach diese .htaccess-Datei bearbeiten und meine paar Skripte wieder aufrufbar machen, aber ich vermute dass das ein Update nicht überlebt. Da ich grundsätzlich auch ein wenig Symfony-Erfahrung habe, dachte ich dass es nicht so schwer sein kann dies korrekt umzusetzen. Aber da habe ich leider falsch gedacht.

    Ich habe nun testweise also einen neuen Controller angelegt:
    PHP-Code:
    <?php declare(strict_types=1);

    namespace 
    App\Controller;

    use 
    Symfony\Component\HttpFoundation\Response;

    class 
    PdfReader extends \Contao\Controller
    {
        public function 
    __construct()
        {
            
    parent::__construct();
        }

        public function 
    showPdf(string $id): Response
        
    {
            die(
    'Hello World');
        }
    }
    Und dann im Verzeichnis config/ eine routing.yml hinzugefügt (die war noch nicht vorhanden, laut Handbuch müsste sie aber wohl dort liegen):
    Code:
    helloworld:
      path: /helloworld
      defaults:
        _controller: App\Controller\PdfReader::showPdf
        _scope: frontend
        _token_check: false
      methods: [GET]
    Das liefert soweit aber nur eine Fehlermeldung im Browser, weil der Controller nicht geladen werden konnte. Das kann ich soweit auch noch beheben, indem ich auch eine services.yml für Symfony anlege (die ebenfalls fehlte):
    Code:
    # config/services.yaml
    services:
      # default configuration for services in *this* file
      _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
    
      # makes classes in src/ available to be used as services
      # this creates a service per class whose id is the fully-qualified class name
      App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
    
      # controllers are imported separately to make sure services can be injected
      # as action arguments even if you don't extend any base controller class
      App\Controller\:
        resource: '../src/Controller'
        tags: ['controller.service_arguments']
    
      App\Controller\PdfReader:
        tags: ['controller.service_arguments']
    An dieser Stelle komme ich nun gefühlt weiter, es wird die Route und der Controller gefunden und scheinbar auch aufgerufen, aber - wenn ich die Fehlermeldung die ich nun erhalte richtig interpretiere - ist der Dependency Injection Container von Symfony nicht korrekt befüllt bzw. gar nicht vorhanden:
    Code:
    [2020-06-27 12:09:13] request.INFO: Matched route "helloworld". {"route":"helloworld","route_parameters":{"_route":"helloworld","_controller":"App\\Controller\\PdfReader::showPdf","_scope":"frontend","_token_check":false},"request_uri":"http://example.com/helloworld","method":"GET"} []
    [2020-06-27 12:09:13] security.INFO: Populated the TokenStorage with an anonymous Token. [] []
    [2020-06-27 12:09:13] request.CRITICAL: Uncaught PHP Exception Error: "Call to a member function has() on null" at /var/www/example/html/contao_49/vendor/contao/core-bundle/src/Resources/contao/library/Contao/System.php line 167 {"exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Call to a member function has() on null at /var/www/example/html/contao_49/vendor/contao/core-bundle/src/Resources/contao/library/Contao/System.php:167)"} []
    Habe ich hier etwas falsch konfiguriert? Gibt es irgendwo Informationen wie diese Konfigurationsdateien aussehen sollten?

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

    Standard

    Nutze den Debug-Mode.

  3. #3
    Contao-Nutzer
    Registriert seit
    29.06.2020.
    Beiträge
    4

    Standard

    Vielen Dank. Habe ich jetzt ausprobiert. Damit bekomme ich das Log mit einem Stack-Trace im Browser zu sehen:
    Code:
    Error:
    Call to a member function has() on null
    
      at vendor/contao/core-bundle/src/Resources/contao/library/Contao/System.php:167
      at Contao\System->import('Contao\\Config', 'Config')
         (vendor/contao/core-bundle/src/Resources/contao/library/Contao/System.php:110)
      at Contao\System->__construct()
         (src/Controller/PdfReader.php:11)
      at App\Controller\PdfReader->__construct()
         (var/cache/dev/ContainerLsajPSn/getPdfReaderService.php:13)
      at require('/var/www/onlinetraining/html/contao_49/var/cache/dev/ContainerLsajPSn/getPdfReaderService.php')
         (var/cache/dev/ContainerLsajPSn/appContao_ManagerBundle_HttpKernel_ContaoKernelDevDebugContainer.php:609)
      at ContainerLsajPSn\appContao_ManagerBundle_HttpKernel_ContaoKernelDevDebugContainer->load('getPdfReaderService.php')
         (vendor/symfony/dependency-injection/Container.php:255)
    Das Problem scheint hier der Konstruktor meines Controllers zu sein, ohne den Aufruf von parent::__construct() funktioniert es deutlich besser. Ist es best practice im Contao-Umfeld den parent-Konstruktor in eigenen Controllern nicht aufzurufen?

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

    Standard

    Poste den Source deines Controllers.

  5. #5
    Contao-Nutzer
    Registriert seit
    29.06.2020.
    Beiträge
    4

    Standard

    Der Quellcode des Controllers hat sich nicht geändert:
    PHP-Code:
    PHP-Code:
    <?php declare(strict_types=1); 

    namespace 
    App\Controller

    use 
    Symfony\Component\HttpFoundation\Response

    class 
    PdfReader extends \Contao\Controller 

        public function 
    __construct() 
        { 
            
    parent::__construct(); 
        } 

        public function 
    showPdf(string $id): Response 
        

            die(
    'Hello World'); 
        } 
    }
    Ich habe nur herausgefunden, dass es scheinbar funktioniert, wenn man den Aufruf von parent::__construct(); entfernt. Scheinbar, weil dann Dienste wie $this->Session, $this->Database etc weiterhin nicht verfügbar zu sein scheinen.

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

    Standard

    Achso, dein Symfony Controller erbt von \Contao\Controller. Das geht natürlich nicht, warum willst du von \Contao\Controller erben?

  7. #7
    Contao-Nutzer
    Registriert seit
    29.06.2020.
    Beiträge
    4

    Standard

    Vielen Dank für die Antwort. Das ist doch schon einmal eine Information die mir völlig neu ist. Ich wollte von diesem Controller ergeben, da ich eine Basisklasse suche mit der ich eine komplette Symfony-Response ausgeben kann. Ich will nichts in das bestehende Template einpassen oder sowas, daher erschienen mir Fragment Controller und Content Element hier ungeeigent. Wie Eingangs geschrieben habe ich quasi gar keine Contao-Erfahrung, kenne nur Symfony selbst.

    Was wäre denn die korrekte Basisklasse für einen Controller der Contao quasi komplett umgehen soll, wobei ich aber trotzdem gerne Dienste wie die Datenbankverbindung und Session verwenden können möchte?

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

    Standard

    Dafür brauchst du keine Basis Klasse. Du kannst natürlich den AbstractController von Symfony als Basis Klasse verwenden. Aber wie gesagt ist das nicht unbedingt notwendig - Dinge wie die Datenbank Verbindung oder die Session kannst du dir ganz normal auch über Dependency Injection holen. Und grundsätzlich hat das ja auch nichts direkt mit Contao zu tun. Du machst es einfach so, wie du es schon von Symfony gewohnt bist.

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
  •