Ergebnis 1 bis 12 von 12

Thema: [Contao 4.9] Hooks in eigenen Bundle über Annotations registrieren

  1. #1
    Contao-Nutzer
    Registriert seit
    07.12.2019.
    Beiträge
    147

    Standard [Contao 4.9] Hooks in eigenen Bundle über Annotations registrieren

    Hallo Contao-Community,

    nachdem ich mich nun mit dem registrieren von Hooks in Contao 4.4 vertraut gemacht habe und mir dazu hier auch sehr schnell geholfen werden konnte, wende ich mich hier nochmal ganz zuversichtlich an euch.

    Hierzu habe ich bereits diesen Thread mitverfolgt, welcher aber noch keinen Erfolg brachte: https://community.contao.org/de/show...S-registrieren

    Ausgangssituation ist folgende:

    Ich habe ein eigenes Bundle verfasst und dieses auch erfolgreich laden lassen. Soweit so gut.

    Der Aufbau ist folgender:

    contao49\bundles\fnjs\test-bundle\src\EventListener\GeneratePageListener.php

    • contao49 ist dabei das Root-Verzeichnis meiner Contao-Installation.
    • bundles ist der ursprüngliche src/ - Ordner aus Contao 4.4.


    In meiner composer.json habe ich einen autload konfiguriert:
    composer.json
    PHP-Code:
    {
        
    "name""contao/managed-edition",
        
    "type""project",
        ..
        .. 
        ..
        
    "minimum-stability""dev",
        
    "prefer-stable"true,
        
    "repositories": [
            {
                
    "type""path",
                
    "url""bundles/fnjs/test-bundle"
            
    }
        ],
        
    "autoload": {
            
    "psr-4": {
                
    "App\\""bundles/"
            
    }
        }




    Ich habe in meinem Bundle eine listener.yml erstellt und dort folgendes eingetragen (https://github.com/contao/contao/issues/1449):

    bundles/fnjs/test-bundle/src/Resources/config/listener.yml:
    Code:
    services:
      fnjs\testBundle\EventListener:
        tags: ['terminal42_service_annotation']
    Diese listener.yml habe ich hier auch laden lassen:

    bundles/fnjs/test-bundle/src/DependencyInjection/testBundleExtension.php
    PHP-Code:
    namespace fnjs\testBundle\DependencyInjection;

    class 
    testBundleExtension extends Extension
    {
        
    /**
         * {@inheritdoc}
         */
        
    public function load(array $mergedConfigContainerBuilder $container)
        {
            
    $loader = new YamlFileLoader(
                
    $container,
                new 
    FileLocator(__DIR__ '/../Resources/config')
            );

            
    $loader->load('services.yml');
            
    $loader->load('listener.yml');
        }




    Die Hook habe ich einfach aus der Contao-Dokumentation übernommen:

    PHP-Code:
    <?php

    // src/EventListener/GeneratePageListener.php
    namespace fnjs\testBundle\EventListener;

    use 
    Contao\CoreBundle\ServiceAnnotation\Hook;
    use 
    Contao\PageRegular;
    use 
    Contao\LayoutModel;
    use 
    Contao\PageModel;
    use 
    Terminal42\ServiceAnnotationBundle\ServiceAnnotationInterface;

    class 
    GeneratePageListener implements ServiceAnnotationInterface
    {
        
    /**
         * @Hook("generatePage")
         */
        
    public function onGeneratePage(PageModel $pageModelLayoutModel $layoutPageRegular $pageRegular): void
        
    {
            
    print_r($pageModel->loadDetails());
        }
    }


    Über den ursprünglichen Weg (das Registrieren der Hook über eine config.php) bekomme ich die Hook zum Laufen.
    Ich würde jedoch gerne den Weg mit den Annotations nachvollziehen und nutzen können, da er mir deutlich angenehmer und eleganter erscheint.

    PS. Ich weiß, dass ich im Bezug auf die Namespaces und Benennung hier noch ein paar "Fehler" hinsichtlich der Symfony-Konventionen habe. Diese werde ich natürlich ausbessern.

    Über etwas Unterstützung dabei würde ich mich sehr freuen und bedanke mich schon mal im Vorraus
    Geändert von Fonjensi (09.05.2020 um 13:23 Uhr)

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

    Standard

    Überprüfe, ob dein Service überhaupt registriert ist:
    Code:
    vendor/bin/contao-console debug:container GeneratePageListener

  3. #3
    Contao-Nutzer
    Registriert seit
    07.12.2019.
    Beiträge
    147

    Standard

    Zitat Zitat von Spooky Beitrag anzeigen
    Überprüfe, ob dein Service überhaupt registriert ist:
    Code:
    vendor/bin/contao-console debug:container GeneratePageListener
    Leider nicht:

    Code:
    ERROR     [console] Error thrown while running command "debug:container GeneratePageListener". Message: "No services found that match "GeneratePageListener"." ["exception" => Symfony\Component\Console\Exception\InvalidArgumentException

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

    Standard

    Dann musst du nacheinander folgende Dinge überprüfen:

    1. Ist die composer.json des Paket korrekt aufgebaut?
    2. Ist das Paket korrekt in der root composer.json eingebunden?
    3. Ist das Autoloading des Pakets korrekt konfiguriert?
    4. Ist das Contao Manager Plugin des Pakets korrekt registriert?
    5. Lässt du das richtige Bundle im Contao Manager Plugin korrekt laden?
    6. Lässt du in der Bundle Extension deine Servicekonfigurationsdatei korrekt laden?
    7. Sind die Services korrekt in der Servicekonfigurationsdatei definiert?
    Geändert von Spooky (09.05.2020 um 15:05 Uhr)

  5. #5
    Contao-Nutzer
    Registriert seit
    07.12.2019.
    Beiträge
    147

    Standard

    Nur zur Info, ich habe nun die Namespaces angepasst.

    Zitat Zitat von Spooky Beitrag anzeigen
    Dann musst du nacheinander folgende Dinge überprüfen:

    1. Ist die composer.json des Paket korrekt aufgebaut?
    2. Ist das Paket korrekt in der root composer.json eingebunden?
    3. Ist das Autoloading des Pakets korrekt konfiguriert?
    4. Ist das Contao Manager Plugin des Pakets korrekt registriert?
    5. Lässt du das richtige Bundle im Contao Manager Plugin korrekt laden?
    6. Lässt du in der Bundle Extension deine Servicekonfigurationsdatei korrekt laden?
    7. Sind die Services korrekt in der Servicekonfigurationsdatei definiert?
    1. Ja, mein Paket wird geladen.
    2. Ja, es kann installiert werden und erscheint auch in meiner composer.json.
    3. Ja, sollte es sein. Das Paket wird geladen und ich kann Veränderungen an den DCAs über das Paket durchführen.

    PHP-Code:
        "autoload": {
            
    "psr-4": {
                
    "Fnjs\\Test\\""src/"
            
    }
        } 
    4. Ja, sonst würde es ja Probleme beim Laden geben, oder?
    5. Ja, es wird das richtige Bundle im Contao Manager Plugin geladen.
    6. Meiner Meinung nach schon. In dieser Datei habe ich es so gelöst:

    PHP-Code:
    class TestBundleExtension extends Extension
    {
        
    /**
         * {@inheritdoc}
         */
        
    public function load(array $mergedConfigContainerBuilder $container)
        {
            
    $loader = new YamlFileLoader(
                
    $container,
                new 
    FileLocator(__DIR__ '/../Resources/config')
            );

            
    $loader->load('services.yml');
            
    $loader->load('listener.yml');
        }

    7. Da bin ich mir recht unsicher, weil ich dazu verschiedene Ansätze gefunden habe.
    Ich habe dort zwei Dateien: services.yml und listener.yml

    services.yml: (Habe ich so aus dem Skeleton-Bundle übernommen)
    PHP-Code:
    services:
        
    _instanceof:
            
    Contao\CoreBundle\Framework\FrameworkAwareInterface:
                
    calls:
                    - [
    "setFramework", ["@contao.framework"]]

            
    Symfony\Component\DependencyInjection\ContainerAwareInterface:
                
    calls:
                    - [
    "setContainer", ["@service_container"]] 
    listener.yml:
    PHP-Code:
    services:
      
    Fnjs\Test\EventListener:
        
    tags: ['terminal42_service_annotation'
    Ich habe es in meiner listener.yml: auch mal mit folgendem versucht (Die Klasse auch direkt mit anzugeben):
    PHP-Code:
    services:
      
    Fnjs\Test\EventListener\GeneratePageListener:
        
    tags: ['terminal42_service_annotation'
    Dann entsteht in meiner IDE (PHPStorm) auch ein Verweis auf die listener.yml, dass dort der Service definiert sei.




    Wie gesagt, kann ich mit meinem Bundle Änderungen an den DCAs durchführen und diese über domain/contao/install auch in der Datenbank anpassen und sie werden mir im Backend angezeigt.
    Nur habe ich ein Problem mit dem registrieren der Hooks und ich denke, dass es dabei an meiner wenigen Erfahrung mit Services liegt.
    Geändert von Fonjensi (09.05.2020 um 17:29 Uhr)

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

    Standard

    Zitat Zitat von Fonjensi Beitrag anzeigen
    listener.yml:
    PHP-Code:
    services:
      
    Fnjs\Test\EventListener:
        
    tags: ['terminal42_service_annotation'
    Das wäre falsch. Laut deiner Beschreibung gibt es so eine Klasse nicht.




    Zitat Zitat von Fonjensi Beitrag anzeigen
    Ich habe es in meiner listener.yml: auch mal mit folgendem versucht (Die Klasse auch direkt mit anzugeben):
    PHP-Code:
    services:
      
    Fnjs\Test\EventListener\GeneratePageListener:
        
    tags: ['terminal42_service_annotation'
    Dann entsteht in meiner IDE (PHPStorm) auch ein Verweis auf die listener.yml, dass dort der Service definiert sei.
    Das wäre korrekt. Wird der Service gefunden, wenn du das so definierst? (ggf. vorher composer install ausführen)

  7. #7
    Contao-Nutzer
    Registriert seit
    07.12.2019.
    Beiträge
    147

    Standard

    Zitat Zitat von Spooky Beitrag anzeigen
    Das wäre falsch. Laut deiner Beschreibung gibt es so eine Klasse nicht.




    Das wäre korrekt. Wird der Service gefunden, wenn du das so definierst? (ggf. vorher composer install ausführen)

    Composer Install habe ich ausgeführt. In der IDE gibt es einen Verweis auf den Service, bzw. die Definition.

    Die Hook wird aber leider noch immer nicht vom System erkannt.

    Was könnte ich noch vergessen haben?

    Muss ich das hier denn irgendwo noch extra laden?

    PHP-Code:
    class TestBundleExtension extends Extension
    {
        
    /**
         * {@inheritdoc}
         */
        
    public function load(array $mergedConfigContainerBuilder $container)
        {
            
    $loader = new YamlFileLoader(
                
    $container,
                new 
    FileLocator(__DIR__ '/../Resources/config')
            );

            
    $loader->load('services.yml');
            
    $loader->load('listener.yml');
        }

    Geändert von Fonjensi (10.05.2020 um 00:48 Uhr)

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

    Standard

    Was ist die Ausgabe von
    Code:
    vendor/bin/contao-console debug:container GeneratePageListener
    mit der korrekten listener.yml?

  9. #9
    Contao-Nutzer
    Registriert seit
    07.12.2019.
    Beiträge
    147

    Daumen hoch

    Zitat Zitat von Spooky Beitrag anzeigen
    Was ist die Ausgabe von
    Code:
    vendor/bin/contao-console debug:container GeneratePageListener
    mit der korrekten listener.yml?
    War wieder ein Error, aber ich habe nun meinen Fehler gefunden, als ich die Symfony - Dateien zur Auflösung der Dependency-Injection angesehen habe.

    Mein Fehler war, dass die Datei in meinem Dependency-Injection Verzeichnis contao49/bundles/fnjs/test/src/DependencyInjection/TestBundleExtension.php hieß.

    Entsprechend wurde auch versucht die Klasse "TestBundleExtension" zu laden.

    Dadurch konnte die vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Bundle/Bundle.php mit folgender Funktion:

    PHP-Code:
     protected function getContainerExtensionClass()
        {
            
    $basename preg_replace('/Bundle$/'''$this->getName());
            return 
    $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension';
        } 
    natürlich nicht viel mit meinem Bundle anfangen, oder eher mit der Dependency-Injection in diesem.

    Stattdessen musste die Datei (und Klasse) so heißen: TestExtension(.php)

    Nun wird alles hier erkannt:

    Code:
    Information for Service "Fnjs\Test\EventListener\GeneratePageListener"
    ======================================================================
    
     ---------------- ---------------------------------------------------------- 
      Option           Value                                                     
     ---------------- ---------------------------------------------------------- 
      Service ID       Fnjs\Test\EventListener\GeneratePageListener              
      Class            Fnjs\Test\EventListener\GeneratePageListener              
      Tags             contao.hook (hook: generatePage, method: onGeneratePage)  
      Public           yes                                                       
      Synthetic        no                                                        
      Lazy             no                                                        
      Shared           yes                                                       
      Abstract         no                                                        
      Autowired        no                                                        
      Autoconfigured   no                                                        
     ---------------- ----------------------------------------------------------

    Vielen Dank für deine ausführliche Hilfe, Spooky

  10. #10
    Contao-Nutzer
    Registriert seit
    07.12.2019.
    Beiträge
    147

    Standard

    Hallo, ich bins nochmal.

    Wusste nicht, ob ich dafür ein neues Thema aufmachen sollte, da es doch sehr ähnlich ist.

    Ich habe diesmal versucht ein Content-Element zu erstellen und das Ganze funktioniert auch, wenn ich keine Annotations verwende.

    Sobald ich aber auf die Annotations setze (wie in der Dokumentation) fehlt mir der Tag:

    (18:49:23) [contao49] php vendor/bin/contao-console debug:container ContentElement

    Code:
    Information for Service "Fnjs\Test\Controller\ContentElement\ExampleElement"
    ============================================================================
    
     ---------------- ---------------------------------------------------- 
      Option           Value                                               
     ---------------- ---------------------------------------------------- 
      Service ID       Fnjs\Test\Controller\ContentElement\ExampleElement  
      Class            Fnjs\Test\Controller\ContentElement\ExampleElement  
      Tags             -                                                   
      Public           no                                                  
      Synthetic        no                                                  
      Lazy             no                                                  
      Shared           yes                                                 
      Abstract         no                                                  
      Autowired        no                                                  
      Autoconfigured   yes                                                 
     ---------------- ---------------------------------------------------- 
    
    
     ! [NOTE] The "Fnjs\Test\Controller\ContentElement\ExampleElement" service or alias has been removed or inlined when the
     !        container was compiled.


    Meine ExampleElement.php mit den Annotations sieht so aus.
    Muss ich hier in den Annotations noch etwas bezüglich der Tags definieren?

    PHP-Code:

    // src/Controller/ContentElement/ExampleElement.php
    namespace Fnjs\Test\Controller\ContentElement;

    use 
    Contao\CoreBundle\Controller\ContentElement\AbstractContentElementController;
    use 
    Contao\CoreBundle\ServiceAnnotation\ContentElement;
    use 
    Contao\ContentModel;
    use 
    Contao\Template;
    use 
    Symfony\Component\HttpFoundation\Request;
    use 
    Symfony\Component\HttpFoundation\Response;

    /**
     * @ContentElement("my_example",
     *   category="media",
     *   template="ce_some_example",
     *   renderer="forward"
     * )
     */
    class ExampleElement extends AbstractContentElementController
    {
        protected function 
    getResponse(Template $templateContentModel $modelRequest $request): ?Response
        
    {
            return 
    $template->getResponse();
        }


    In meiner listener.yml habe ich nun schon einiges probiert (wie man am auskommentierten Code sehen kann).
    Wenn ich ohne Annotations arbeite und alles wie in Contao 4.6 über die listener/services.yml definiere, funktioniert es.
    Nur bei den Annotations wirft es leider einen Fehler:

    Code:
    services:
      _defaults:
        autoconfigure: true
    
      Fnjs\Test\EventListener\GeneratePageListener:
        tags: ['terminal42_service_annotation']
    
      Fnjs\Test\Controller\ContentElement\ExampleElement:
        #tags: ['contao.content_element']
        #autoconfigure: true
        #autowire: true
    
        #tags:
        #- name: contao.content_element
        #  category: texts
        #  method: getResponse
        #  renderer: esi
        #  type: my_custom_type
    Vielleicht vergesse/übersehe ich ja irgendwo eine Kleinigkeit.

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

    Standard

    Sollte mit folgender Service Definition funktionieren:
    Code:
    services:
      _defaults:
        autoconfigure: true
    
      Fnjs\Test\EventListener\GeneratePageListener: ~
    
      Fnjs\Test\Controller\ContentElement\ExampleElement: ~
    In der Annotation solltest du
    Code:
    renderer="forward"
    entfernen, außer du hast das aus einem bestimmten Grund gesetzt.

  12. #12
    Contao-Nutzer
    Registriert seit
    07.12.2019.
    Beiträge
    147

    Standard

    Zitat Zitat von Spooky Beitrag anzeigen
    Sollte mit folgender Service Definition funktionieren:
    Code:
    services:
      _defaults:
        autoconfigure: true
    
      Fnjs\Test\EventListener\GeneratePageListener: ~
    
      Fnjs\Test\Controller\ContentElement\ExampleElement: ~
    In der Annotation solltest du
    Code:
    renderer="forward"
    entfernen, außer du hast das aus einem bestimmten Grund gesetzt.

    Hey Spooky,

    habe die listener.yml nun genauso angepasst, wie du oben vorgeschlagen hast und das "renderer=forward" entfernt.

    Leider weiterhin so:

    Code:
    Information for Service "Fnjs\Test\Controller\ContentElement\ExampleElement"
    ============================================================================
    
     ---------------- ---------------------------------------------------- 
      Option           Value                                               
     ---------------- ---------------------------------------------------- 
      Service ID       Fnjs\Test\Controller\ContentElement\ExampleElement  
      Class            Fnjs\Test\Controller\ContentElement\ExampleElement  
      Tags             -                                                   
      Public           no                                                  
      Synthetic        no                                                  
      Lazy             no                                                  
      Shared           yes                                                 
      Abstract         no                                                  
      Autowired        no                                                  
      Autoconfigured   yes                                                 
     ---------------- ---------------------------------------------------- 
    
    
     ! [NOTE] The "Fnjs\Test\Controller\ContentElement\ExampleElement" service or alias has been removed or inlined when the
     !        container was compiled.

    #########################

    Edit: Keine Ahnung wieso, aber nun funktioniert es, ohne dass ich etwas geändert habe.
    Auch keine Änderungen am Composer, Autoload, etc.

    Seltsam.
    Geändert von Fonjensi (10.05.2020 um 22:05 Uhr)

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
  •