Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Scope bei Klassen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] Scope bei Klassen

    Ich weiß nicht so recht, wie ich mein Problem betiteln sollte. Es ist eine, zumindest für mich, komplexe Sache, in der ich alleine nicht mehr durchblicke.

    Ich teste etwas Softwaredesign und habe mich an den Beispielen im Netz orientiert einen Registrationscontroller gebaut.
    PHP-Code:
    class RegistrationController extends Controller
    {
        public function 
    execute()
        {
            
    $form = new RegistrationForm;

            if(
    $this->request->issetPost()) {
                
    $posts $this->request->getPosts();
                if(
    $form->isValid($posts)) {
                    
    // [..save..]
                
    }
            }
        }

    Danach wird in der RegistrationForm in der Methoe isValid($posts) die Prüfung durchgenommen und bei Fehlern die Methode Registry::getInstance()->validator->setErrors($this->errors) befüllt.

    Da ich dachte, dass die Registry einen Container darstellt, in dem das Objekt validator im aktuellen Zustand enthalten ist, habe ich diese im View aufgerufen.

    newuserview.php
    PHP-Code:
    </head>
    <body>
        <?php
            $fehler 
    Registry::getInstance()->validator->getErrors();
            if(
    $fehler) {
                foreach(
    $fehler as $fehlermeldung) {
                    echo 
    '<p>'$fehlermeldung '</p>';
                }
            }

        
    ?>
        <form accept-charset="utf-8" action="newuser.php" method="post">
    Aber die Registry::getInstance()->validator->getErrors() ist leer. Lasse ich das Objekt validator in der RegistrationForm ausgeben lasse, ist sie befüllt aber im view ist sie leer. Greif die view aber nicht auf dasselbe Objekt in der Registry?

    Oder wo sollten die Fehler, welche in der RegistrationForm->isValid() entdeckt werden, zwischengespeichert werden, damit die View sie sich holen kann, wenn das Formular nicht ordentlich befüllt wurde?

  • #2
    Klingt nach Typischer Fall von ver-pointert, irgendwie fehlt da noch die Registry Class in deinen Qoutes
    [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

    Kommentar


    • #3
      Die Registry wird in der Bootstrap befüllt. Also noch bevor mit switch-case-Dingern die einzelnen Urls zugewiesen werden.

      Kommentar


      • #4
        Ich kann ja gerne die Registry-Klasse hier einfügen. Die richtet sich ebenfalls an den Beispielen in den Foren.
        PHP-Code:
        class Registry
        {
            private static 
        $_instance null;
            private 
        $_cache = array();

            public static function 
        getInstance()
            {
                if(
        null === self::$_instance) {
                    
        self::$_instance = new self;
                }
                return 
        self::$_instance;
            }


            public function 
        __set($index$value) {

                if(!empty(
        $index) && is_string($index)  && !array_key_exists($index$this->_cache)) {
                    
        $this->_cache[$index] = $value;
                }
                else {
                    
        // Errorhandling here ...
                
        }
            }

            public function 
        __get($name)
            {
                if(
        array_key_exists($name$this->_cache) && !empty($this->_cache[$name])) {
                    return 
        $this->_cache[$name];
                }
                else {
                    return 
        null;
                }
            }

            public function 
        __unset($index)
            {
                unset(
        $this->_cache[$index]);
            }


            private function 
        __construct() {}
            private function 
        __clone() { }

        Kommentar


        • #5
          Mir gings jetzt nicht ums Wo, eher ums Wie, ansonsten Uri-Geller' ich da wenig raus. Interessant wärs zu wissen ob bspw. validator ein public-$ ist oder ob es ein return einer __get()-methode ist, falls es das ist sei sicher das die __get()-methode keine kopie der registry-variable übergibt sondern einen pointer.

          http://www.php.net/manual/de/languag...references.php
          [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

          Kommentar


          • #6
            Hier ist die Bootstrap.php. Vielleicht macht es dir die Sache deutlicher.
            PHP-Code:
            // bootstrap.php

            $registry Registry::getInstance();
            $registry->database  = new Database;
            $registry->route     = new Router;
            $registry->validator = new Validator;
            $registry->request   Request::getRequests();

            switch(
            $registry->request->getUrl()) {

                case 
            'news':
                    
            $news = new NewsController;
                    
            $news->listNews();
                    break;
                case 
            'users':
                    
            $news = new UserController;
                    
            $news->getUser($id);
                    break;
                case 
            'loremipsum':
                    
            $news = new LoremIpsumController;
                    
            $news->loremIpsum();
                    break;
                default:
                    echo 
            'hier ist die startseite';
                    break;

            Kommentar


            • #7
              Okay, ich schau mal ob ich dich auf den Weg bekomme.

              Was glaubst du wohin du schreibst wenn du das __get jeder klasse so beschreibst die dort verwickelt ist:

              PHP-Code:
              public function __get($what) {
                return isset(
              $this->whatever[$what]) ? $this->whatever[$what] : false;

              Und dann so versucht wird zu schreiben:

              Code:
              $test->test2->test3->test4->test5->blub = test;
              geh davon aus das die klassen bis 'blub' alle existent sind, was würde dann

              PHP-Code:
              echo $test->test2->test3->test4->test5->blub
              ausgeben ?
              [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

              Kommentar


              • #8
                $test = Registry-Objekt;
                $test->test2 = Objekt einer beliebigen Klasse, welche mit Registry::__get() ins Registry::$_cache[] geschrieben wird.
                $test->test2->test3 = public Variable oder Methode des Objekts im Registry::$_cache[].
                $test->test2->test3->test4->test5->blub = das weiß ich nicht.

                Wenn ich also in RegistrationsForm Registry::getInstance()->validator->setErrors($this->errors) aufrufe, ist es bis Registry::getInstance()->validator doch der Rückgabewert in der Registry::__get('validator), also mein Validator-Objekt. Und da die Klasse setErrors() als public deklariert wurde, kann ich diese doch überall im Code befüllen, also somit das im Registry::_cache gespeicherte Objekt.

                Kommentar


                • #9
                  Zitat von tr0y Beitrag anzeigen
                  Mir gings jetzt nicht ums Wo, eher ums Wie, ansonsten Uri-Geller' ich da wenig raus. Interessant wärs zu wissen ob bspw. validator ein public-$ ist oder ob es ein return einer __get()-methode ist, falls es das ist sei sicher das die __get()-methode keine kopie der registry-variable übergibt sondern einen pointer.

                  PHP: Objekte und Referenzen - Manual
                  hast du da reingeschaut ?

                  PHP-Code:
                  // ich brauch mal ne klasse
                  $test = new klasse();

                  // ich schreib da mal was rein
                  $test->objekt "testobjekt";

                  // ich möchte jetzt mal das objekt anders verwenden
                  $test2 $test;

                  // da schreib ich auch was rein
                  $test2->objekt "testobjekt mit anderem text?";

                  // nun lern ich referenzieren
                  $test = &$test2;

                  // nun schreib ich was in $test !
                  $test->objekt "Ich bin ein Test!";

                  // nun schau ich mir $test2 an...

                  echo $test2->objekt;  # wird ausgeben: 'Ich bin ein Test' 
                  Kannst du erahnen worauf ich hinaus will ?
                  [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

                  Kommentar


                  • #10
                    Ich verstehe, was du meinst. Aber dadurch, dass die Registry ein Singleton ist, rufe ich dann nicht automatisch immer dasselbe Registry-Objekt mit den gleichen Klassenobjekten im cache-Container auf?

                    Kommentar


                    • #11
                      Zitat von tr0y Beitrag anzeigen
                      // ich möchte jetzt mal das objekt anders verwenden
                      $test2 = $test;

                      // da schreib ich auch was rein
                      $test2->objekt = "testobjekt mit anderem text?";
                      Zitat von tr0y Beitrag anzeigen
                      // nun lern ich referenzieren
                      $test = &$test2;

                      // nun schreib ich was in $test !
                      $test->objekt = "Ich bin ein Test!";
                      Kleine Anmerkung dazu, die beiden Code-Abschnitte bewirken beide, dass nachher sowohl $test->objekt als auch $test2->objekt die selbe (veränderte) Ausgabe liefern.

                      Beim Zuweisen von Objekten wird das Objekt nicht kopiert sondern nur der interne Zeiger darauf (das ist nicht das selbe wie PHP Referenzen!). Den Effekt, den du vermutlich im ersten Teil erreichen wolltest bekommst du mit
                      Code:
                      $test2 = clone $test;
                      [IMG]https://g.twimg.com/twitter-bird-16x16.png[/IMG][URL="https://twitter.com/fschmengler"]@fschmengler[/URL] - [IMG]https://i.stack.imgur.com/qh235.png[/IMG][URL="https://stackoverflow.com/users/664108/fschmengler"]@fschmengler[/URL] - [IMG]http://i.imgur.com/ZEqflLv.png[/IMG] [URL="https://github.com/schmengler/"]@schmengler[/URL]
                      [URL="http://www.schmengler-se.de/"]PHP Blog[/URL] - [URL="http://www.schmengler-se.de/magento-entwicklung/"]Magento Entwicklung[/URL] - [URL="http://www.css3d.net/"]CSS Ribbon Generator[/URL]

                      Kommentar


                      • #12
                        Zitat von fab Beitrag anzeigen
                        Kleine Anmerkung dazu, die beiden Code-Abschnitte bewirken beide, dass nachher sowohl $test->objekt als auch $test2->objekt die selbe (veränderte) Ausgabe liefern.

                        Beim Zuweisen von Objekten wird das Objekt nicht kopiert sondern nur der interne Zeiger darauf (das ist nicht das selbe wie PHP Referenzen!). Den Effekt, den du vermutlich im ersten Teil erreichen wolltest bekommst du mit
                        Code:
                        $test2 = clone $test;
                        jop, eine Kopie, danke für die korrektur

                        Allerdings:

                        returns von funktionen liefern meines erachtens nur dann auch die speicheradresse wieder wenn ich der methode in ihrer definition explizit mitteile, richtig ? ( Mir ist das jetzt nicht ganz klar was passiert wenn _nicht_ da ich von eh und je automatisch explizit referenziere wenn ichs auch will )

                        ergo:

                        PHP-Code:
                        function &__get() { ... return $this->object["irgendwas"]; } # referenz 
                        PHP-Code:
                        function __get() { ... return $this->object["irgendwas"]; } # keine referenz, kopie. 
                        Irre ich mich da grade ?
                        [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

                        Kommentar


                        • #13
                          Auf die Gefahr hin, dass das hier OT wird

                          Das ist prinzipiell schon richtig, aber aufpassen musst du falls $this->object["irgendwas"] wieder ein Objekt ist. Wie ich schon sagte, geht es dabei nicht um Referenzen (die wiederum keine Zeiger auf Speicheradressen im herkömmlichen Sinne sind!) sondern um Objektzeiger.

                          Siehe auch:

                          Was Referenzen nicht sind
                          Objekte und Referenzen

                          Edit: Oh und noch was, IIRC ist es nicht möglich magische Methoden wie __get derartig zu deklarieren und das Referenz-Symbol & in deinem Beispiel würde ignoriert.
                          [IMG]https://g.twimg.com/twitter-bird-16x16.png[/IMG][URL="https://twitter.com/fschmengler"]@fschmengler[/URL] - [IMG]https://i.stack.imgur.com/qh235.png[/IMG][URL="https://stackoverflow.com/users/664108/fschmengler"]@fschmengler[/URL] - [IMG]http://i.imgur.com/ZEqflLv.png[/IMG] [URL="https://github.com/schmengler/"]@schmengler[/URL]
                          [URL="http://www.schmengler-se.de/"]PHP Blog[/URL] - [URL="http://www.schmengler-se.de/magento-entwicklung/"]Magento Entwicklung[/URL] - [URL="http://www.css3d.net/"]CSS Ribbon Generator[/URL]

                          Kommentar


                          • #14
                            Zitat von fab Beitrag anzeigen
                            Auf die Gefahr hin, dass das hier OT wird

                            Das ist prinzipiell schon richtig, aber aufpassen musst du falls $this->object["irgendwas"] wieder ein Objekt ist. Wie ich schon sagte, geht es dabei nicht um Referenzen (die wiederum keine Zeiger auf Speicheradressen im herkömmlichen Sinne sind!) sondern um Objektzeiger.

                            Siehe auch:

                            Was Referenzen nicht sind
                            Objekte und Referenzen

                            Edit: Oh und noch was, IIRC ist es nicht möglich magische Methoden wie __get derartig zu deklarieren und das Referenz-Symbol & in deinem Beispiel würde ignoriert.
                            hm ja, macht sinn, dann verwerf die idee mit der Refenzierung, dein Code funktioniert so ( __get / __set betreffend ).

                            Sicher das die Error-Registrierung das macht was sie soll ?
                            [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

                            Kommentar


                            • #15
                              Irgendwie bin ich jetzt nicht schlauer, als vorhin. Die einzelnen Schritte sind ja folgende:

                              1 --> RegistrationController ruft new RegistrationForm auf
                              2 --> RegistrationForm includiert eine FormularView, prüft bei action die Angaben
                              3 --> Ist Prüfung korrekt, dann speichere und ShowNewUserView.php weiterleiten.. ansonsten nochmal FormularView ausgegeben.

                              Und über all dem steht die Registry-Singleton, die sozusagen als globaler Objektcontainer agieren soll.

                              Das Registry-Objekt sieht bei den einzelnen Schritten so aus:

                              1 --> RegistrationController ruft new RegistrationForm auf
                              Code:
                              Registry Object
                              (
                                  [_cache:Registry:private] => Array
                                      (
                                          [validator] => Validator Object
                                              (
                                                  [value:Validator:private] =>
                                                  [error:Validator:private] =>
                                                  [errorContainer:Validator:private] =>
                                              )
                              
                                          [request] => Request Object
                                              (
                                                  [requests:Request:private] => Array
                                                      (
                                                          [post] => Array
                                                              (
                                                                  [username] =>
                                                                  [email] =>
                                                                  [name] =>
                                                                  [birthdate] =>
                                                              )
                                                      )
                                              )
                                      )
                              )
                              2 -->RegistrationForm includiert eine FormularView, prüft bei action die Angaben >> Angaben sind falsch, also Fehlermeldungen in Registry::getInstance()->validator->setErrors($fehler) reinschreiben. Registry-Objekt dann:
                              Code:
                              Registry Object
                              (
                                  [_cache:Registry:private] => Array
                                      (
                                          [validator] => Validator Object
                                              (
                                                  [value:Validator:private] =>
                                                  [error:Validator:private] =>
                                                  [errorContainer:Validator:private] => Array
                                                      (
                                                          [username] => Username fehlt
                                                          [email] => Emailadresse fehlt
                                                          [name] => Name fehlt
                                                          [birthdate] => Geburtsdatum fehlt
                                                      )
                                              )
                              
                                          [request] => Request Object
                                              (
                                                  [requests:Request:private] => Array
                                                      (
                                                          [post] => Array
                                                              (
                                                                  [username] =>
                                                                  [email] =>
                                                                  [name] =>
                                                                  [birthdate] =>
                                                              )
                                                      )
                                              )
                                      )
                              )
                              3 --> Prüfung gibt false zurück, also FormularView nochmal ausgeben und darin auf die Methode Registry::getInstance()->validator->getErrors() zugreifen. Registry-Objekt hier aber wieder leer:
                              Code:
                              Registry Object
                              (
                                  [_cache:Registry:private] => Array
                                      (
                                          [validator] => Validator Object
                                              (
                                                  [value:Validator:private] =>
                                                  [error:Validator:private] =>
                                                  [errorContainer:Validator:private] => 
                                              )
                              
                                          [request] => Request Object
                                              (
                                                  [requests:Request:private] => Array
                                                      (
                                                          [post] => Array
                                                              (
                                                                  [username] =>
                                                                  [email] =>
                                                                  [name] =>
                                                                  [birthdate] =>
                                                              )
                                                      )
                                              )
                                      )
                              )
                              Sind in der Registry-Singleton nicht die gleichen Objekte enthalten, so dass Veränderung an den Objekten beim Aufruf des Registry-Singleton nicht auch an anderen Orten des Codes auswirken?

                              Kommentar

                              Lädt...
                              X