Contao-Camp 2024
Ergebnis 1 bis 4 von 4

Thema: Eventlistener per Annotation bei Datensatzerstellung

  1. #1
    Contao-Nutzer
    Registriert seit
    03.10.2020.
    Beiträge
    41

    Standard Eventlistener per Annotation bei Datensatzerstellung

    Hallo,

    ich setze MetaModels 2.2 auf Contao 4.9 ein und möchte beim Erstellen eines Datensatzes im Frontend in MetaModels in das Datenfeld arc_tlmember_id die ID des gerade angemeldeten Members schreiben.
    Hierzu bin ich durch einen Beitrag im Forum auf das Event PreEditModelEvent gestoßen. Damit funktioniert dies auch mit dem folgenden Code:
    PHP-Code:
    <?php
    // src/EventListener/TestListener.php

    namespace App\EventListener;

    use 
    ContaoCommunityAlliance\DcGeneral\Event\PreEditModelEvent
    use 
    ContaoCommunityAlliance\DcGeneral\Event\PostPersistModelEvent
    use 
    Terminal42\ServiceAnnotationBundle\Annotation\ServiceTag;
    use 
    Doctrine\DBAL\Connection
    use 
    Contao\FrontendUser;
    use 
    Contao\CoreBundle\Routing\ScopeMatcher;
    use 
    Symfony\Component\HttpFoundation\RequestStack;
    use 
    Contao\CoreBundle\Monolog\ContaoContext
    use 
    Psr\Log\LogLevel

    /**
     * @ServiceTag("kernel.event_listener", event=PreEditModelEvent::NAME)
     */

    class TestListener
    {
        public function 
    __invoke(PreEditModelEvent $event):void 
            

                
    $strMetaModelNameConst 'mm_dz_arc_artikelcontent';

                
    $strMetaModelName $event->getEnvironment()->getDataDefinition()->getName();
                
    $myScope TL_MODE;
                
                if (
    'FE' !== TL_MODE
                
    || $strMetaModelNameConst != $strMetaModelName){ 
                    return;
                } else 
                {
                    
    $Meldung ="Sind im FE in " $strMetaModelName;
                    
    $myMemberID = \Contao\FrontendUser::getInstance()->id;
                    
    /** @var \MetaModels\DcGeneral\Data\Model $model */
                    
    $model $event->getModel();
                    
    $mmId $model->getItem()->get('id');
                    
    $myOwnerArray $model->getItem()->get('arc_tlmember_id');
                    
    $myOwner $myOwnerArray['id'];

                    if (empty(
    $myOwner)){
                        
    $SchreibeMemberID "Ja";
                        
    $db = \Contao\System::getContainer()->get('database_connection');
                        
    $count $db->executeStatement("UPDATE mm_dz_arc_artikelcontent SET arc_tlmember_id=? WHERE id=?", array($myMemberID$mmId));
                    }
                }

                \
    System::getContainer()
                    ->
    get('monolog.logger.contao')
                    ->
    log(LogLevel::INFO'TEST - Scope=' $myScope ' - Tabelle=' $strMetaModelName ' - Meldung: ' $Meldung ' - myOwner=' $myOwner ' - MemberID=' $myMemberID ' - DBCount=' $count ' - MM-Id='$mmId ' - SchreibeMemberID=' $SchreibeMemberID, array(
                    
    'contao' => new ContaoContext(__CLASS__.'::'.__FUNCTION__TL_GENERAL
                
    )));
            }
    }
    Allerdings ist das Event doch nicht ideal, da der Datensatz zu dem Zeitpunkt ja noch nicht existiert. Daher habe ich es stattdessen mit dem Event PostPersistModelEvent versucht. Hier erhalte ich aber die Fehlermeldung
    Code:
    request.CRITICAL: Uncaught PHP Exception TypeError: "Argument 1 passed to App\EventListener\TestListener::__invoke() must be an instance of ContaoCommunityAlliance\DcGeneral\Event\PostPersistModelEvent, instance of ContaoCommunityAlliance\DcGeneral\Event\PreEditModelEvent given, called in /html/contao/vendor/symfony/event-dispatcher/EventDispatcher.php on line 304" at /html/contao/src/EventListener/TestListener.php line 22 {"exception":"[object] (TypeError(code: 0): Argument 1 passed to App\\EventListener\\TestListener::__invoke() must be an instance of ContaoCommunityAlliance\\DcGeneral\\Event\\PostPersistModelEvent, instance of ContaoCommunityAlliance\\DcGeneral\\Event\\PreEditModelEvent given, called in /html/contao/vendor/symfony/event-dispatcher/EventDispatcher.php on line 304 at /html/contao/src/EventListener/TestListener.php:22)"} []
    Da ich noch nicht viel Erfahrung mit php habe verstehe ich das so, das es die Methode __invoke für PostPersistModelEvent nicht gibt.

    Ich habe das Forum dazu schon intensiv durchsucht, bin aber leider nicht weiter gekommen.
    Hinweise sind herzlich willkommen.

  2. #2
    Contao-Nutzer
    Registriert seit
    03.10.2020.
    Beiträge
    41

    Standard

    Nachdem ich einige Lernstunden verbracht habe und mit dem Debug-Modus gearbeitet habe bin ich auf folgende Lösung gekommen. Dazu habe ich einfach nur die function wie von Contao debug vorgeschlagen ändern müssen.

    PHP-Code:
    /**
     * @ServiceTag("kernel.event_listener", event=PostPersistModelEvent::NAME)
     */

    class WriteMemberId2DZArticleListener
    {
        public function 
    onDcGeneralModelPostPersist($event)
            { 
                
    $strMetaModelNameConst 'mm_dz_arc_artikelcontent';

                
    $strMetaModelName $event->getEnvironment()->getDataDefinition()->getName();
                
    $myScope TL_MODE;
                
                if (
    'FE' !== TL_MODE
                
    || $strMetaModelNameConst != $strMetaModelName)
                {
                    
    //$Meldung ="Scope ist BE oder falsche MM-Tabelle";
                    
    return; 
    Nun tut es beim Sichern des Datensatzes und es erscheint auch keine Fehlermeldung mehr.

    In einem nächsten Schritt würde ich gerne die Prüfung 'FE' !== TL_MODE (da laut Doku deprecated) gegen den ScopeMatcher tauschen. Muss ich mir dazu die public function isFrontend() extra erstellen?

  3. #3
    Contao-Urgestein Avatar von zonky
    Registriert seit
    19.03.2010.
    Ort
    Berlin, Rdf
    Beiträge
    9.682
    User beschenken
    Wunschliste

    Standard

    Zitat Zitat von stu Beitrag anzeigen
    Hallo,

    ich setze MetaModels 2.2 auf Contao 4.9 ein und möchte beim Erstellen eines Datensatzes im Frontend in MetaModels in das Datenfeld arc_tlmember_id die ID des gerade angemeldeten Members schreiben.
    das Posting wäre wohl im Bereich MM besser aufgehoben gewesen... ;-)

    Für Deinen Fall hätte ich eher das PrePersistModelEvent empfohlen - das wird "kurz vor dem Speichern" eines Datensatzes zündet.

    Hier kann man noch Daten manipulieren und hat neben dem neuen Model (Daten aus der Maske) auch noch die Daten des alten Model (Daten in DB) zur Verfügung - damit kann man z.B. auf Änderungen prüfen.

    An der Stelle könntest Du dem Datensatz die Member-ID übergeben und kannst Dir das gemurkse mit executeStatement sparen!

    $model hat auch getter und setter für die Attribute, so dass Du Dir den Umweg über das Item auch sparen könntest.

  4. #4

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
  •