Context nicht bekannt bei Aufruf über eine Action

Im Entwickler-Forum können Implementierungsdetails sowie Alternativen der Umsetzung diskutiert werden. // Here, developers can discuss implementation details of features of their projects.
Antworten
Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Context nicht bekannt bei Aufruf über eine Action

Beitrag von dave » 03.11.2016, 19:33:04

Ich habe mal wieder ein Problem, dass ich einfach nicht geregelt bekomme.

Ich rufe eine Klasse die vom APFObject erbt, via Action durch den ServiceManager auf. Dort ist dann allerdings nur die Sprache bekannt, der Context ist leer. Warum, was mache ich falsch?

Ein paar Codestellen:

Code: Alles auswählen

class UploadAction extends AbstractFrontcontrollerAction {
   public function run() {
      $test = $this->getServiceObject('APF\extensions\fileupload\biz\TestManager', [array('name' => $this->getInput()->getParameter('name'))]);

      exit();
   }
}   
 
Die Action wird durch eine Taglib nach dem Absenden eines Formulares gefeuert und durch den LinkGenerator erzeugt.

Code: Alles auswählen

class TestManager extends APFObject {
   public function __construct($options = null) {

      echo $this->getContext();
      // get configuration (check was done in taglib)
      $config = $this->getConfiguration('APF\extensions\fileupload', 'config.ini')->getSection($options['name']);

      $this->test();
   }

   protected function test() {
      echo 'This is a test';
   }
}
 
Problem ist nun:
Configuration with namespace "APF\extensions\fileupload", context "", language "de", environment "DEFAULT", and name "config.ini" cannot be loaded
Aber ich kann es einfach nicht nachvollziehen.

Kontext wird in der bootstrap natürlcih gesetzt und wenn ich mir den einfach mal in der Action durch ein echo ausgebe, ist er auch da.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Context nicht bekannt bei Aufruf über eine Action

Beitrag von dr.e. » 03.11.2016, 21:26:50

Hi!

habe ich das richtig verstanden, dass du die Action vom ServiceManager erzeugen lässt? Sofern die Action durch den Frontcontroller erzeugt wird, sollten dort Context und Sprache injiziert werden (siehe APF\core\frontcontroller\Frontcontroller::addAction()). Ich habe das lokal nachvollzogen und bekomme ein korrektes Ergebnis.

Magst du nochmal ein bisschen mehr Code posten, wie du die Action erzeugst/erzeugen lässt?
Viele Grüße,
Christian

Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Context nicht bekannt bei Aufruf über eine Action

Beitrag von dave » 03.11.2016, 22:17:38

Nicht ganz :D
In der Action wird die neue Klasse FileHandler durch den ServiceManager erstellt. Es war etwas ungünstig ausgedrückt.

Gerne noch mehr Code:
Die Action wird durch den LinkGenerator in einer eigenen Taglib in der Methode transform erzeugt:

Code: Alles auswählen

class FileUploadTag extends Document {
   public function transform() {
      $actionLink = LinkGenerator::generateActionUrl(Url::fromCurrent(), 
         'APF\extensions\fileupload', 
         'FileUpload', 
         ['name' => $this->getAttribute('name')]);

      $html = '<input id="' . 
         $this->getAttribute('id') . 
         '" type="file" name="' . 
         $this->getAttribute('name') . 
         '" data-url="' . 
         $actionLink . '" multiple>';

      return $html;
    }
} 
Die Config zur Action ist simpel:

Code: Alles auswählen

[FileUpload]
ActionClass = "APF\extensions\fileupload\actions\UploadAction"
Die Action ansich steht bereits im ersten Post.

Was mir einfach komisch ist, dass die Sprache injiziert wurde, der Context aber nicht :?

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Context nicht bekannt bei Aufruf über eine Action

Beitrag von dr.e. » 04.11.2016, 13:57:49

Hallo dave,

das ist in der Tat komisch. Ich hatte dazu ein ähnliches Beispiel mit der APF Doku-Page (SetModelAction) ausprobiert und vorher eine beliebige Sprache und einen anderen Context in der index.php definiert. Die dort definierten Werte sind bei jedem Aufruf in der Action verfügbar gewesen.

Dein Vorgehen ist absolut valide und der Anwendungsfall sollte auch so funktonieren - bei einem Post gegen ?APF_extensions_fileupload-action:FileUpload=name=xyz sollte der Front-Controller die Action erzeugen und mit Sprache und Context ausstatten.

Kannst du mal versuchen zu debuggen, wo der Context verlohren geht? Gute Breakpoints wären Frontcontroller.php:339 und Frontcontroller.php:209. Vielleicht finden wir das Problem so. :?
Viele Grüße,
Christian

Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Context nicht bekannt bei Aufruf über eine Action

Beitrag von dave » 04.11.2016, 23:15:56

So gesehen bin ich erstmal froh, dass es kein grober Fehler meinerseits ist :lol: Trotzdem ist es extrem ärgerlich, den Fehler einfach nicht finden zu können. An der jetzigen Stelle erreiche ich auch langsam meine Kenntnisse was OOP angeht :roll:

Ich habe mal ein print_r($action) in Zeile 213 des Frontcontroller.php eingefügt.

Folgendes erhalte ich:

Code: Alles auswählen

APF\extensions\fileupload\actions\UploadAction Object
(
    [actionNamespace:protected] => APF\extensions\fileupload
    [actionName:protected] => FileUpload
    [input:protected] => APF\core\frontcontroller\FrontcontrollerInput Object
        (
            [action:APF\core\frontcontroller\FrontcontrollerInput:private] => APF\extensions\fileupload\actions\UploadAction Object
 *RECURSION*
            [parameters:protected] => Array
                (
                )

            [context:protected] => 
            [language:protected] => de
            [serviceType:protected] => 
            [isInitialized:protected] => 
        )

    [type:protected] => prepagecreate
    [keepInUrl:APF\core\frontcontroller\AbstractFrontcontrollerAction:private] => 
    [frontController:APF\core\frontcontroller\AbstractFrontcontrollerAction:private] => APF\core\frontcontroller\Frontcontroller Object
        (
            [actionStack:protected] => Array
                (
                    [0] => APF\extensions\fileupload\actions\UploadAction Object
 *RECURSION*
                )

            [urlMappingsByToken:APF\core\frontcontroller\Frontcontroller:private] => Array
                (
                )

            [urlMappingsByNamespaceAndName:APF\core\frontcontroller\Frontcontroller:private] => Array
                (
                )

            [context:protected] => preisdb
            [language:protected] => de
            [serviceType:protected] => 
            [isInitialized:protected] => 
        )

    [context:protected] => preisdb
    [language:protected] => de
    [serviceType:protected] => 
    [isInitialized:protected] => 
)
Hoffentlich hilft dir das etwas weiter. Was deutlich zu sehen ist, dass der Context beim FrontcontrollerInput fehlt, die Language ist aber da.

Mein Code ist jetzt auf ein Minimum reduziert. Ich kann dir auch gerne nochmal alles zusammen zukommen lassen.

Zusätzlich noch der Stacktrace. Darüber habe ich den Context auch nochmal verfolgt. Bis zum ServiceManager ist dieser verfügbar, beim Singleton kann ich ihn nicht abfragen und beim TestManager fehlt er dann :?:

Code: Alles auswählen

APF\core\frontcontroller\Frontcontroller->start()  /is/htdocs/wp1177661_MI1CO4T11E/www/preis-db/multifileupload.php  16  
APF\core\frontcontroller\Frontcontroller->runActions()  /is/htdocs/wp1177661_MI1CO4T11E/www/preis-db/APF/core/frontcontroller/Frontcontroller.php  157  
APF\extensions\fileupload\actions\UploadAction->run()  /is/htdocs/wp1177661_MI1CO4T11E/www/preis-db/APF/core/frontcontroller/Frontcontroller.php  217  
APF\core\pagecontroller\APFObject->getServiceObject()  /is/htdocs/wp1177661_MI1CO4T11E/www/preis-db/APF/extensions/fileupload/actions/UploadAction.php  21  
APF\core\service\ServiceManager::getServiceObject()  /is/htdocs/wp1177661_MI1CO4T11E/www/preis-db/APF/core/pagecontroller/APFObject.php  167  
APF\core\singleton\Singleton::getInstance()  /is/htdocs/wp1177661_MI1CO4T11E/www/preis-db/APF/core/service/ServiceManager.php  83  
ReflectionClass->newInstanceArgs()  /is/htdocs/wp1177661_MI1CO4T11E/www/preis-db/APF/core/singleton/Singleton.php  82  
APF\extensions\fileupload\biz\TestManager->__construct()  /is/htdocs/wp1177661_MI1CO4T11E/www/preis-db/APF/core/singleton/Singleton.php  82  
APF\core\pagecontroller\APFObject->getConfiguration()  /is/htdocs/wp1177661_MI1CO4T11E/www/preis-db/APF/extensions/fileupload/biz/TestManager.php  17  
APF\core\configuration\ConfigurationManager::loadConfiguration()  /is/htdocs/wp1177661_MI1CO4T11E/www/preis-db/APF/core/pagecontroller/APFObject.php  185  
APF\core\configuration\provider\ini\IniConfigurationProvider->loadConfiguration()  /is/htdocs/wp1177661_MI1CO4T11E/www/preis-db/APF/core/configuration/ConfigurationManager.php  133 


Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Context nicht bekannt bei Aufruf über eine Action

Beitrag von dave » 08.11.2016, 13:30:58

Nochmal ein Update:

Mein print_r(action) in Zeile 213 des Frontcontroller.php hat keinerlei Aussagekraft :roll: Das sieht so genauso auch bei meiner UMGTAutoLogin-Action aus, und dit klappt einwandfrei

Meine Erkenntnis ist jetzt: Der Context ist ausschliesslich in der __construct()-Methode meiner Klasse nicht verfügbar. Warum ist mir völlig schleierhaft.
Im Frontcontroller nachverfolgt ist der Context nach dem Ausführen der ersten Action im Modus "prepagecreate" verloren. Es verhält sich so, als würde meine neue Klasse den Context mit "null" überschreiben. Mache ich aber nicht ;)

Ich habe bereits daran gedacht, dass es irgendwo am InputFilter hängt. Daher übergebe ich einfach mal keine Werte meiner Klasse. Aber auch das klappt führt zu keiner Verbesserung. Ich verstehe es einfach nicht.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Context nicht bekannt bei Aufruf über eine Action

Beitrag von dr.e. » 27.11.2016, 19:54:42

Hallo dave,

sooo, nun bin ich wieder da! :) War ein sehr schöner Urlaub und ich hatte richtig viel Spass und Erholung.

Habe mir zwischen Fotos sichten eine kleine Auszeit genommen und mir dein Problem nochmal von Beginn an angesehen. Fazit: ich hätte dir auch schon früher helfen können sollen, das Problem nur in der Hektik vor dem Urlaub aber offensichtlich einfach übersehen... :roll:

Aber nun zu den Details:
  • Beim Erzeugen einer Action injiziert der Front-Controller jeder Action nach der Konstruktion den aktuellen Kontext und die aktuell definierte Sprache (=diejenige, die dem Front-Controller in der index.php mitgegeben wurde). Damit steht der Kontext (und an sich auch die Sprache) erst bei der Ausführung der (Interface-)Methode run() zur Verfügung und nicht im Konstruktor.
  • Die Service-Klasse TestManager wird korrekt in der run()-Methode der Action erzeugt und damit ist auch sichergestellt, dass nach Aufruf der Methode getServiceObject() ein vollständig initialisiertes Objekt (inkl. Kontext und Sprache) zur Verfügung steht.
  • Innerhalb von TestManager::__contstruct() versuchst du nun eine Konfiguration zu laden, Kontext (und auch Sprache, aber dazu später) ist nicht vorhanden. Das liegt daran, dass der Aufruf von getServiceObject() intern den ServiceManager nutzt, der ebenfalls auf Setter-Injection setzt und daher Kontext und Sprache erst nach der Konstruktion injiziert (siehe Front-Controller oben). Damit kann im Konstruktor des TestManager noch kein Kontext (und auch keine Sprache) zur Verfügung stehen.
  • Der Effekt mit der Sprache - und das ist zugegeben extrem verwirrend - liegt daran, dass der Wert "de" der Standard-Wert aus APFObject ist zwar vermutlich der gleiche wie in deiner Anwendung, aber nicht der von dir gesetzte. Somit ist auch die Sprache im Konstruktor nicht wirklich verfügbar, sondern nur mit dem Standard-Wert belegt. Um das für die Zukunft einfacher zu gestalten, entferne ich den Standard-Wert gleich noch.
  • Rufst du innerhalb deines Konstruktors nun eine Methode auf, die ebenfalls Kontext und/oder Sprache benötigt - wie getConfiguration() - geht das natürlich schief. Lösung ist hier, die gewünchte Aktion erst zu einem späteren Zeitpunkt auszuführen, beispielsweise durch Aufruf einer Methode TestManager::uploadFile() aus der UploadAction::run(). Damit ist innerhalb von uploadFile() auch Kontext und Sprache verfügbar und dein getConfiguration() klappt.
Anbei mein funktionierender Code:

Code: Alles auswählen

namespace DEV\test;

use APF\core\frontcontroller\AbstractFrontcontrollerAction;

class UploadAction extends AbstractFrontcontrollerAction {

   public function run() {

      $test = $this->getServiceObject('\DEV\test\TestManager', [['name' => $this->getInput()->getParameter('name')]]);

      // Kontext und Sprache verfügbar
      $context = $this->getContext();
      $lang = $this->getLanguage();

      // Kontext und Sprache jetzt auch im TestManager verfügbar
      $test->uploadFile();

   }
}

Code: Alles auswählen

namespace DEV\test;

use APF\core\pagecontroller\APFObject;

class TestManager extends APFObject {

   public function __construct(array $options = null) {
      // Kontext und Sprache noch nicht verfügbar
      $context = $this->getContext();
      $lang = $this->getLanguage();

      $this->test();
   }

   protected function test() {
      // Kontext und Sprache noch nicht verfügbar
      $context = $this->getContext();
      $lang = $this->getLanguage();
   }

   public function uploadFile() {
      // Kontext und Sprache verfügbar
      $context = $this->getContext();
      $lang = $this->getLanguage();
   }

}
Hoffe das hilft dir nun wirklich weiter! :)

PS: Um das Verhalten besser zu verdeutlichen habe ich in die Doku unter http://adventure-php-framework.org/Seit ... iceManager eine Warnung aufgenommen.

PPS: Entfernen der Standard-Initialisierug läuft unter http://tracker.adventure-php-framework. ... php?id=312.
Viele Grüße,
Christian

Benutzeravatar
dave
Beiträge: 903
Registriert: 04.02.2011, 19:03:57
Wohnort: Berlin
Kontaktdaten:

Re: Context nicht bekannt bei Aufruf über eine Action

Beitrag von dave » 01.12.2016, 17:52:46

Hallo Christian,
schön zu hören dass du ne gute Auszeit hattest :) So soll es ja auch sein.

Gut, Ok, dann erstmal vielen Dank für die Erläuterung. Dann ist das also kein Bug oder Fehler sondern durch die Implementierung so gewollt. Prima, damit kann ich leben.

PS: Top. Auch für mich verständlich ^^
PPS: Auch top. :D

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Context nicht bekannt bei Aufruf über eine Action

Beitrag von dr.e. » 03.12.2016, 17:56:37

Freue mich, dass ich dir helfen konnte! :)
Viele Grüße,
Christian

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast