MB: assoziative Werte mit __set() und Index in numerisches array einfügen?

moin,

kann man mit der Interzeptor-Methode __set() auf irgend eine weise Werte in ein existierendes numerisches Array Property der Klasse Foobar einfügen? Was in etwa so aussieht?

class Foobar {
  
  private $array;
  
  public function __set( string $property, array $value ) {
    if( $property === 'array' ) {
      $this->$property = $value;
    }
  }
}

und das sowas machen?

$fb = new Foobar;
$fb->tok[ $i ] = [ 'fu' => 'baz' ];

das mit einer Array-Erstellung mit $fb->tok = [ /* array */ ]; krig ich hin, jedoch habe ich keine Ahnung, wie ich Werte mit __set() in ein existierendes numerisches Array mit Index rein bringen kann, wie ich im Anwendungsbeispiel erläutert habe.

lgmb

  1. Tach!

    kann man mit der Interzeptor-Methode __set() auf irgend eine weise Werte in ein existierendes numerisches Array Property der Klasse Foobar einfügen?

    Die Methode __set() eines Objekts wird aufgerufen, wenn auf nicht zugreifbare (zum Beispiel weil nicht existente) Eigenschaften zugegriffen wird. Was du dann tust, hat mit __set() nichts mehr zu tun. Dass du also auf Eigenschaften eines Arrays zugreifst, ist unabhängig von __set().

    und das sowas machen?

    $fb = new Foobar;
    $fb->tok[ $i ] = [ 'fu' => 'baz' ];
    

    In der zweiten Zeile findet zuerst ein Lesezugriff auf $fb->tok statt. Wenn das nicht existiert, wird erstmal __get() aufgerufen.

    Der Zugriff auf $fb->tok[$i] hat nun nichts mehr mit dem Objekt in $fb zu tun, da greifen also keine magischen Methoden dieses Objekts mehr. Ein Zugriff der gezeigten Art kann nur klappen, wenn entweder tok existiert und ein Array oder String ist, oder wenn __get() ein Array oder String zurückgibt. Mit String wird es aber eine Notice geben und ein eher nicht erwartetes Ergebnis.

    dedlfix.

    1. moin

      schuldige die Verzögerung. Ich habs gelöst und meinte sowas:

      <?php
      
      class Foobar {
          
          private $array;
          
          public function __get( string $name ) {
              return $this->$name;
          }
          
          public function __set( string $name, $value ) {
              if( $name === 'array' and is_array($value )) {
                  $this->array[] = $value;
              }
          }
          
      }
      
      $fb = new Foobar;
      
      $fb->array = [ 'a' => '1' ];
      $fb->array = [ 'b' => '2' ];
      $fb->array = [ 'c' => '3' ];
      $fb->array = [ 'd' => '4' ];
      $fb->array = [ 'e' => '5' ];
      
      echo '<pre>';
      var_dump( $fb->array );
      
      ?>
      

      Resultat:

      array(5) {
        [0]=>
        array(1) {
          ["a"]=>
          string(1) "1"
        }
        [1]=>
        array(1) {
          ["b"]=>
          string(1) "2"
        }
        [2]=>
        array(1) {
          ["c"]=>
          string(1) "3"
        }
        [3]=>
        array(1) {
          ["d"]=>
          string(1) "4"
        }
        [4]=>
        array(1) {
          ["e"]=>
          string(1) "5"
        }
      }
      

      Das ist das von mir erwünschte ergebis. Was hast du denn gedacht, was ich meine? Ich möht gerne Wissen woran es hakt, bezogen auf deine Interpretation meiner Frage. Für eine bessere Kommunikation meinerseits ist dies essenziell

      lgmb

      1. Tach!

        Das ist das von mir erwünschte ergebis. Was hast du denn gedacht, was ich meine?

        Ich habe gedacht, dass du die Funktionsweise von __set() falsch verstanden hast. Das ging mir beim ersten Versuch seinerzeit auch so.

        kann man mit der Interzeptor-Methode __set() auf irgend eine weise Werte in ein existierendes numerisches Array Property der Klasse Foobar einfügen?

        Das war dein erster Satz, und nein, man kann mit __set() nicht auf Elemente eines Array zugreifen, weil Arrays kein __set() haben. Man kann damit nur Schreibzugriffe auf nicht vorhandene Eigenschaften eines Objektes abfangen. Ein Zugriff auf Elemente eines Arrays ist aber keine solche Operationen.

        Ein Array ist ein komplexer Typ, bestehend einerseits aus dem Array selbst, als Verwaltungsstruktur für die Elemente und andererseits aus den Elementen. Schreib-/Lesezugriffe auf Eigenschaften eines Objektes (oder Variablen allgmein), die ein Array sind, greifen nur auf das Array selbst zu, nicht jedoch auf dessen Elemente. Das geht auch mit __get()/__set() nicht anders. Man kann also mit __set() nur ein ganzes Array hinzufügen, nicht aber auf dessen Elemente zugreifen. Das wäre nämlich ein Lesezugriff auf das Array mit anschließender Operation auf den Elementen.

        Oder als Code formuliert, mit einfacher Variable statt Objekt-Eigenschaft, weil es dasselbe Prinzip ist:

        // Schreibzugriff auf $foo, legt ein Array an,
        // als Voraussetzung für die nachfolgende Operation
        $foo = [];
        
        // zuerst erfolgt ein Lesezugriff auf $foo,
        // anschließend Zugriff auf Element mit Index 42,
        // in dem Fall eine Schreiboperation
        $foo[42] = 'bar';
        
        // zuerst erfolgt wieder ein Lesezugriff auf $foo,
        // anschließend Zugriff auf Element mit Index 42,
        // in dem Fall eine Leseoperation
        echo $foo[42];
        

        Wenn du hingegen ein Array privat verwalten möchtest, und alle Zugriffe kontrolliert werden sollen, wäre das eher über die Implementation des Interfaces ArrayAccess zu erledigen.

        Ich möht gerne Wissen woran es hakt, bezogen auf deine Interpretation meiner Frage.

        Das Beispiel machte etwas anderes als deine erste Frage war. Es setzte eine Eigenschaft, wenn deren Name 'array' war. Das war jedenfalls kein Array-Zugriff.

        Anschließend fragtest du

        und das sowas machen?

        $fb = new Foobar;
        $fb->tok[ $i ] = [ 'fu' => 'baz' ];
        

        Damit greifst du lesend auf eine Eigenschaft namens tok zu. Gesetzt hast du oben aber eine Eigenschaft namens 'array'. Weiter gings es mit:

        [...] jedoch habe ich keine Ahnung, wie ich Werte mit __set() in ein existierendes numerisches Array mit Index rein bringen kann, wie ich im Anwendungsbeispiel erläutert habe.

        Wieder das Verständnisproblem deinerseits. Mit __set() geht sowas nicht, weil der Zugriff auf das Array ein Lesezugriff ist, also __get() oder direkt, wenn die Eigenschaft schon existiert und public ist. Das "mit Index rein bringen" findet dann im Array statt, nicht mehr im Objekt.


        Deine Lösung, die du nun präsentierst, hat nur noch was mit dem Schreiben ganzer Arrays zu tun, nicht jedoch mit den im Ausgangsposting erwähnten Zugriffen auf die Elemente, was Schreiben und Lesen beinhalten würde. Es wäre vermutlich verständlicher gewesen, wenn du geschrieben hättest, was du eigentlich möchtest, und nicht nach Details zu etwas fragst, das du für die Lösung gehalten hast. Zudem kam da noch dein Verständnisproblem mit der richtigen Verwendung der Technik hinzu.

        Deine jetzige Implementation von __set() macht etwas sehr unerwartetes. Es sieht aus, als ob du einer Eigenschaft Werte zuweist. In Wirklichkeit hängst du aber diese Werte an ein bestehendes Array an. Schon die Verwendung magischer Methoden ist etwas, das eine besondere Aufmerksamkeit beim Code-Leser benötigt, um zu verstehen, warum da keine Eigenschaften direkt verwendet werden. Und hier muss nun der Verwender wissen, dass er anscheinend die Eigenschaft immer wieder überschreiben muss, um in Wirklichkeit etwas anzuhängen. Sowas ist Aufgabe für eine Methode namens append(), nicht aber für Magie mit __set().

        dedlfix.

        1. moin,

          Schreib-/Lesezugriffe auf Eigenschaften eines Objektes (oder Variablen allgmein), die ein Array sind, greifen nur auf das Array selbst zu, nicht jedoch auf dessen Elemente. Das geht auch mit __get()/__set() nicht anders. Man kann also mit __set() nur ein ganzes Array hinzufügen, nicht aber auf dessen Elemente zugreifen. Das wäre nämlich ein Lesezugriff auf das Array mit anschließender Operation auf den Elementen.

          Das habe ich im laufe dieses Forums begriffen :-).

          Wenn du hingegen ein Array privat verwalten möchtest, und alle Zugriffe kontrolliert werden sollen, wäre das eher über die Implementation des Interfaces ArrayAccess zu erledigen.

          soweit ich mir den Code angucke, ist es ähnlich wie bei Getters und Setters.

          Das Beispiel machte etwas anderes als deine erste Frage war. Es setzte eine Eigenschaft, wenn deren Name 'array' war. Das war jedenfalls kein Array-Zugriff.

          Das habe ich begriffen danke für den hinweis.

          Es wäre vermutlich verständlicher gewesen, wenn du geschrieben hättest, was du eigentlich möchtest, und nicht nach Details zu etwas fragst, das du für die Lösung gehalten hast.

          Ok ich versuche mein Problem ausdruck zu verleihen und mit Code Beispielen diese Frage zu begräftigen. Wenn da eine differenz bezüglich Code und Frage auftauchen, tuts mir leid. Leider fälls mir bei der formulierung der frage nicht auf 😕.

          Deine jetzige Implementation von __set() macht etwas sehr unerwartetes. Es sieht aus, als ob du einer Eigenschaft Werte zuweist. In Wirklichkeit hängst du aber diese Werte an ein bestehendes Array an.

          das ist mein Ziel gewesen.

          Schon die Verwendung magischer Methoden ist etwas, das eine besondere Aufmerksamkeit beim Code-Leser benötigt, um zu verstehen, warum da keine Eigenschaften direkt verwendet werden.

          Verstehe Danke für den Hinweis.

          Sowas ist Aufgabe für eine Methode namens append(), nicht aber für Magie mit __set().

          Ich glaube du hast meine Zielvorgabe nicht richtig verstanden:

          • Es sollen bedingt Werte angehängt werden
          • Es soll nicht verändert werden (WICHTIG)
          • Es muss ein Objekt mit Properties sein

          Konstanten des Objekts kann ich nicht machen, da es ja zur laufzeit variabel konstruiert wird.

          lgmb

          1. Tach!

            Ich glaube du hast meine Zielvorgabe nicht richtig verstanden:

            Vielleicht hab ich sie doch (zumindest teilweise) verstanden, erachte das Vorgehen aber nicht als erstrebenswert. Darfst du auch ignorieren, am Ende musst du damit glücklich werden, ich äußere nur Bedenken.

            • Es sollen bedingt Werte angehängt werden

            Anhängen ist jedenfalls nicht wiederholtes Zuweisen.

            • Es muss ein Objekt mit Properties sein

            Das ist nicht sinnvoll, wenn das heißt, dass ein bekannter Mechanismus so umgebogen wird, dass er etwas anderes macht.

            dedlfix.

            1. moin,

              Vielleicht hab ich sie doch (zumindest teilweise) verstanden, erachte das Vorgehen aber nicht als erstrebenswert. Darfst du auch ignorieren, am Ende musst du damit glücklich werden, ich äußere nur Bedenken.

              ok verstanden

              • Es sollen bedingt Werte angehängt werden

              Anhängen ist jedenfalls nicht wiederholtes Zuweisen.

              richtig

              • Es muss ein Objekt mit Properties sein

              Das ist nicht sinnvoll, wenn das heißt, dass ein bekannter Mechanismus so umgebogen wird, dass er etwas anderes macht.

              Ok ich werde es überdenke. Ich muss aber wiederhjolt betonben das es nur zum Lern unbd Test zwecken geeignet ist.

              lgmb

  2. Hallo @MB

    schau Dir mal die ArrayObject-Klasse aus der SPL an.

    This class allows objects to work as arrays.

    Beispiel:

    <?php
    
    class FooBar extends ArrayObject {
        
        public function baz(){
            return 'baz';
        }
        
    }
    
    $fb = new Foobar;
    $fb[] = 'wert 1';
    $fb[] = 'wert 2';
    $fb['mykey'] = 'myvalue';
    $fb[0] = 'ueberschreibt wert 1';
    
    // Testausgabe:
    
    var_dump($fb);
    echo $fb[1] . PHP_EOL;
    echo $fb['mykey'] . PHP_EOL;
    echo $fb->baz();
    

    Teste es: https://3v4l.org/NudFU

    1. moin,

      schau Dir mal die ArrayObject-Klasse aus der SPL an.

      Ok. Meine Intension ist, Zugriff auf ein public Property eines Objektes zu haben, welches von der programmlogik nicht oder bedingt verändert werden darf.

      sehr trivial habe ich das gemacht:

      class FooBar {
      
          private $baz;
      
          public function baz(){
              return $this->baz;
          }
          
      }
      

      ... in die zielführende Richtung in PHP habe ich das gemacht ...

      class FooBar {
      
          private $baz;
      
          public function __get( string $property ) {
              return $this->$property;
          }
      }
      

      ...und Erreichung der Intension ...

      class FooBar {
      
          private $fuz;
          private $baz;
      
          public function __get( string $property ) {
              return $this->$property;
          }
          
          public function __set( string $property, $value ) {
              if( $property === 'fuz' and is_string( $value ) ) { 
                  $this->fuz = $value;
              }
              if( $property === 'baz' and is_array( $value ) ) { 
                  $this->baz = $value;
              }
          }
      }
      

      am ende hat das Progrämmchen den gewünschten effekt:

      • Objekt
      • Public Property (keine Getters & Setters)
      • nicht oder bedingt änderbar

      😉

      lgmb

      1. Tach!

        Ok. Meine Intension ist,

        Intention mit t. Intens... wäre ein Fall für intensiv.

        Zugriff auf ein public Property eines Objektes zu haben, welches von der programmlogik nicht oder bedingt verändert werden darf.

        Das ist nun schon wieder was anderes. Nun ist es nur noch ein einfacher Getter/Setter als Kapselung des Zugriffs auf private Eigenschaften, und ohne Array. Was möchtest du wirklich?

            public function __set( string $property, $value ) {
                if( $property === 'fuz' and is_string( $value ) ) { 
                    $this->fuz = $value;
                }
                if( $property === 'baz' and is_array( $value ) ) { 
                    $this->baz = $value;
                }
            }
        }
        

        DRY (don't repeat yourself) statt WET (write everything twice). Wenn noch 13 solcher Eingeschaften hinzukommen, schreibst du 15 mal dasselbe nur mit anderem Variablennamen? Prüf den Namen gegen eine einfach erweiterbare Liste, beispielsweise mit in_array(). Die Prüfung von $value und das Zuweisen geht dann als einmal geschriebener Code.

        dedlfix.

        1. moin,

          Tach!

          Ok. Meine Intension ist,

          Intention mit t. Intens... wäre ein Fall für intensiv.

          Sry, checke ich nich

          Nun ist es nur noch ein einfacher Getter/Setter als Kapselung des Zugriffs auf private Eigenschaften, und ohne Array. Was möchtest du wirklich?

          ich möchte dieses Konstrukt eben gerade verhindern.

          DRY (don't repeat yourself) statt WET (write everything twice).

          Jo ich versuche es eben gerade mit meimner Lösung.

          Wenn noch 13 solcher Eingeschaften hinzukommen, schreibst du 15 mal dasselbe nur mit anderem Variablennamen?

          checke ich net sry.

          Prüf den Namen gegen eine einfach erweiterbare Liste, beispielsweise mit in_array(). Die Prüfung von $value und das Zuweisen geht dann als einmal geschriebener Code.

          kannst du bitte n kleines Klassen Code beispiel geben, damit ich das besser begreife.

          lgmb

          1. Tach!

            Ok. Meine Intension ist,

            Intention mit t. Intens... wäre ein Fall für intensiv.

            Sry, checke ich nich

            Intention schreibt sich mit t, nicht mit s. Du kannst aber auch "Absicht" nehmen.

            Nun ist es nur noch ein einfacher Getter/Setter als Kapselung des Zugriffs auf private Eigenschaften, und ohne Array. Was möchtest du wirklich?

            ich möchte dieses Konstrukt eben gerade verhindern.

            Warum führst du es dann als Beispiel dafür an, was du möchtest? Weniger Verwirrung und ständige Änderungen des Ziels würde die Sache einfacher machen.

            Wenn noch 13 solcher Eingeschaften hinzukommen, schreibst du 15 mal dasselbe nur mit anderem Variablennamen?

            checke ich net sry.

            Deine Lösung ist sehr wiederholend. Mir ist dabei auf den ersten Blick auch nicht aufgefallen, dass die Typprüfungen unterschiedlich sind. Wenn du an einer solchen Lösung feststelst, dass da was grundlegend anders gemacht werden muss, dann musst du diese Änderung an vielen Stellen vornehmen anstatt nur an einer. Deswegen Wiederholungen meiden.

            Das Problem an __get/__set ist auch noch, dass es nur dieses eine Funktionspaar ist, das sich um die Zugriffe kümmert, und man alles darin abwickeln muss, auch wenn es für die einzelnen Eigenschaften individuell ist. Um die Komplexität gering zu halten, sind viele Programmierer bestrebt, das Single-Responsibility-Prinzip einzuhalten.

            Prüf den Namen gegen eine einfach erweiterbare Liste, beispielsweise mit in_array(). Die Prüfung von $value und das Zuweisen geht dann als einmal geschriebener Code.

            kannst du bitte n kleines Klassen Code beispiel geben, damit ich das besser begreife.

            Aus dem Kopf geschrieben, kann Fehler enthalten:

            function __set($name, $value) {
              $stringProperties = ['foo', 'bar'];
              $arrayProperties = ['qux', 'baz'];
            
              if (in_array($name, $stringProperties) and is_string($value)) {
                $this->$name = $value;
              } else if (in_array($name, $arrayProperties) and is_array($value)) {
                $this->$name = $value;
              } else {
                // Fehlerbehandlung
              }
            }
            

            Wenn nun String und/oder Array-Eigenschaften hinzukommen, dann muss nur noch deren Name ins jeweilige Array eingetragen werden. Zudem weisen nun die Namen $stringProperties und $arrayProperties deutlich darauf hin, was für ein Typ beabsichtigt ist.

            dedlfix.

            1. moin,

              Intention schreibt sich mit t, nicht mit s. Du kannst aber auch "Absicht" nehmen.

              ups, kleiner syntaktischer fehler, sry.

              Um die Komplexität gering zu halten, sind viele Programmierer bestrebt, das Single-Responsibility-Prinzip einzuhalten.

              Das ist mein Bestreben.

              lgmb

              1. Hallo,

                syntaktischer fehler

                Nein, das hatte mit Syntax nichts zu tun. Am besten du vermeidest einfach alle Fremdworte! 😉

                Gruß
                Kalk

                1. moin,

                  syntaktischer fehler

                  Nein, das hatte mit Syntax nichts zu tun. Am besten du vermeidest einfach alle Fremdworte! 😉

                  sry, ich meine or­tho­gra­fisch.

                  Ich muss doch mal weiter aushohlen als mir lieb is. Das is so eine Sache bei mir: "inkludiert", "include", "beinhalted" bedeuten bekanntlich das selbe. Wenn mir aber der gebräuchliche Begriff auf die schnelle nicht einfällt und ich im formulierungsfluss - besser gesagt zwang - bin, bediene ich mich eben Synonyme die mir einfallen damit meine Formulierung, die noch nicht zu Papier gebracht worden ist, nicht aufgehalten wird. Ich mach das nicht aus reiner Arroganz. Oft verwechsel ich auch Wört die ähnliches bedeuten aber nicht gleich sind wie hier und merke es nicht einmal. Ich bitte dies zu entschuldigen 😕. Sprecht mich einfach drauf an wenn ungereimt heiten auftretten sowie hier 😉.

                  lgmb

                  1. Hallo,

                    auf die schnelle

                    Zum Glück lesen wir hier im Forum ja nicht sofort, was du tippst. Das geht ja erst nachdem du die Nachricht abgeschickt hast. Der Moment vor dem Abschicken ist genau der Moment, sich das Geschriebene nochmal anzuschauen.

                    Schau, du bist ja nicht der Einzige mit Problemen. Du z.B. hast Formulierungsprobleme, ich zum Beispiel hab Leseprobleme. Nicht korrekte Formulierungen, Tippfehler u.Ä. lenken mich dermaßen ab, dass ich gar nicht zur Lösungsfindung komme. Andere mögen wieder andere Probleme haben...

                    Gruß
                    Kalk

                    1. moin,

                      auf die schnelle

                      Zum Glück lesen wir hier im Forum ja nicht sofort, was du tippst.

                      jepp

                      Schau, du bist ja nicht der Einzige mit Problemen.

                      wie wahr

                      Du z.B. hast Formulierungsprobleme,

                      das strengt echt dermaßen an. aber heut gehts

                      ich zum Beispiel hab Leseprobleme. Nicht korrekte Formulierungen, Tippfehler u.Ä. lenken mich dermaßen ab, dass ich gar nicht zur Lösungsfindung komme.

                      krass! Sry wegen meiner abenteuerlichsten formulierungen. Aber ich hoffe sehr es wird mit derzeit besser.

                      lgmb

            2. Tach!

              function __set($name, $value) {
                $stringProperties = ['foo', 'bar'];
                $arrayProperties = ['qux', 'baz'];
              
                if (in_array($name, $stringProperties) and is_string($value)) {
                  $this->$name = $value;
                } else if (in_array($name, $arrayProperties) and is_array($value)) {
                  $this->$name = $value;
                } else {
                  // Fehlerbehandlung
                }
              }
              

              Wenn nun String und/oder Array-Eigenschaften hinzukommen, dann muss nur noch deren Name ins jeweilige Array eingetragen werden. Zudem weisen nun die Namen $stringProperties und $arrayProperties deutlich darauf hin, was für ein Typ beabsichtigt ist.

              Mir fiel grad noch ein, dass die eigentliche Frage sein sollte, ob die Typprüfung zur Laufzeit sinnvoll ist oder eher weniger. Aber die kann ich nicht beantworten, das musst du mit deinem Anwendungsfall abstimmen. Ich kann nur ein paar Gedanken zwecks Abwägung geben.

              Laufzeitprüfungen sind dann sinnvoll, wenn der Typ oder Inhalt zur Laufzeit variabel oder ungesichert sein können. Das sind zum Beispiel einige der Eingaben, beispielsweise vom Anwender oder von aderen Quellen kommend.

              Zudem kann man sich die Frage stellen, ob die Typprüfung auch fachlich unabdingbar ist. Was passiert wenn da was mit falschem Typ kommt? Wenn der Anwender Müll eingibt, kann er zwar erwarten, dass die Anwendung souverän damit umgeht und nicht abstürzt, aber nicht unbedingt, dass dabei was sinnvolles rauskommt.

              Laufzeitprüfungen sind aber weniger sinnvoll, wenn der Typ zur Entwicklungszeit sichergestellt werden kann oder zumindest von der IDE als problematisch angekreidet wird. Das ist zum Beispiel dann der Fall, wenn es lediglich darum geht, Aufmerksamkeitsfehler des Programmierers abzufangen. Das kann und sollte man zur Entwicklungszeit korrigieren. IDEs, die Codeanalyse eingebaut haben, sind hierzu ein passendes Werkzeug.

              Wenn also eine Eigenschaft keine weiteren Einschränkungen hat, als dass der Typ sicherzustellen ist, dann ist im Prinzip ein PHPDoc-Kommentar mit Typangabe ausreichend, wenn mir dann alle Verwendungen angekreidet werden, an denen der zu übergebende Wert nicht eindeutig ist.

              dedlfix.

      2. class FooBar {
        
            private $fuz;
            private $baz;
        
            public function __get( string $property ) {
                return $this->$property;
            }
            
            public function __set( string $property, $value ) {
                if( $property === 'fuz' and is_string( $value ) ) { 
                    $this->fuz = $value;
                }
                if( $property === 'baz' and is_array( $value ) ) { 
                    $this->baz = $value;
                }
            }
        }
        

        Das ist natürlich wirklich sehr kurz, aber damit erkaufst du dir auch ein paar Nachteile: Die Autovervollständigung von Editoren leidet darunter, wenn Typ-Informationen, sowie hier, erst zur Laufzeit bekannt werden. Das selbe gilt für Code-Qualitäts-Tools, die auf statische Typ-Informationen angewiesen sind und letztlich erschwerst du dir selber das Unit-Testing, wenn du es denn benutzt. Wenn es etwas länger sein darf, aber ohne die genannten Nachteile, dann würde ich es so schreiben:

        class FooBar {
        
            private $fuz;
        
            private $baz;
        
            public function setFuz(string $fuz) {
                $this->fuz = $fuz;
            }
        
            public function getFuz() : string {
                return $this->fuz;
            }
        
            public function setBar(array $bar) {
                $this->bar = $bar;
            }
        
            public function getBar() : array {
                return $this->bar;
            }
        }
        

        Oder, du benutzt PHPDoc-Annotationen, damit wird der Code sogar noch kürzer als deine ursprüngliche Fassung und viele Programme können damit umgehen:

        class FooBar {
        
            /**
             * @var string
             */
            public $fuz;
        
            /**
             * @var array
             */
            private $baz;
        }
        
        1. moin,

          Das ist natürlich wirklich sehr kurz, aber damit erkaufst du dir auch ein paar Nachteile:

          Ich wollte mit einer Klasse einen Pseudo Datentyp erstellen und das wie gefordert von einer anderen Klassen im Konstruktor mit HintType und Interfaces einbringen. So erspart man sich verfälschungen und ich komm damit sehr gut klar. Klar kann man das So machen

          new DB(
            Cfg::getDNS(),
            Cfg::getUser(),
            Cfg::getPWD(),
            Cfg::getChar()
          );
          

          Nach dieser lösung muss man dann aber auch über umwege arbeiten können. viel simpler ist es so new DB( new TypDB );und da muss man nur ein Property aufrufen $this->TypeDB->char oder $this->TypeDB->dns und drauf zugreifen und keine Methode aufrufen in etwa so $this->TypeDB->getChar() natürlich mit ausnahme der Interzeptor Method __set() . Das finde ich persönlich unpassend und meine lösung eleganter.

          Oder, du benutzt PHPDoc-Annotationen, damit wird der Code sogar noch kürzer als deine ursprüngliche Fassung und viele Programme können damit umgehen:

          Ich hab erwähnt das ich öffentliche Methoden die verändert werden können nicht mag. Ich kenn mich, ich renn dann kopflos in irgendwas rein.

          lgmb

          1. Hallo MB,

            das Thema Auto-Vervollständigung und PHPDoc, a.k.a. IntelliSense, interessiert Dich nicht?

            Wenn Du deinen Code so schreibst, dass ein brauchbarer Editor Dich nicht unterstützten kann, verwendest läufst Du viel eher in irgendwas 'rein.

            Wenn Du einen Editor hast, der solche Funktionen nicht anbietet, dann ist er eigentlich nicht brauchbar.

            Darüber hinaus erkaufst Du Dir mit magic methods einen deutlichen Laufzeitnachteil im Vergleich zu expliziten Gettern und Settern. Der Nachteil ist natürlich, dass Du mit Gettern und Settern einen Haufen Boilerplate-Code schreiben musst. Hier würde ein Makro-Präprozessor in PHP helfen, um das zu kompaktifizieren, aber den gips nicht.

            Rolf

            --
            sumpsi - posui - clusi
            1. Tach!

              Darüber hinaus erkaufst Du Dir mit magic methods einen deutlichen Laufzeitnachteil im Vergleich zu expliziten Gettern und Settern. Der Nachteil ist natürlich, dass Du mit Gettern und Settern einen Haufen Boilerplate-Code schreiben musst. Hier würde ein Makro-Präprozessor in PHP helfen, um das zu kompaktifizieren, aber den gips nicht.

              Aber es gibt IDEs mit Live Templates oder Snippets oder wie auch immer diese Helfer genannt worden sind, die Codestücke einfügen.

              dedlfix.

            2. moin,

              das Thema Auto-Vervollständigung und PHPDoc, a.k.a. IntelliSense, interessiert Dich nicht?

              Ich bitte dich. Was soll das.

              Wenn Du deinen Code so schreibst, dass ein brauchbarer Editor Dich nicht unterstützten kann, verwendest läufst Du viel eher in irgendwas 'rein.

              ok. es ist ja nur um ein Interface zu ersetzen und nicht mehr.

              class Foobar
                public function __construct( Fu $f, Baz $b  ) {}
              }
              $fb = new Foobar( new Fu, new Baz );
              

              Darüber hinaus erkaufst Du Dir mit magic methods einen deutlichen Laufzeitnachteil im Vergleich zu expliziten Gettern und Settern.

              habe ich mir gedacht. Aber ich hab leider kein PHP-Debugger Programm der mir anschaulich die Laufzeit, Speicher, und den Aufwand den dert Code aufbringen muss presentiert

              lgmb

              1. das Thema Auto-Vervollständigung und PHPDoc, a.k.a. IntelliSense, interessiert Dich nicht?

                Ich bitte dich. Was soll das.

                Ich glaube, das hast du in den falschen Hals gekriegt. Rolfs Frage war glaube ich sehr ernst gemeint. Denn magische Methoden wirken leider so, dass sie das Editieren schwieriger machen, aus den schon genannten Gründen.

            3. moin,

              das Thema Auto-Vervollständigung und PHPDoc, a.k.a. IntelliSense, interessiert Dich nicht?

              sry rolf. Ich Nutze IntelliSense wirklich inteniv. Es ist geil. Da wo ich __set() und __get() einsetze, ist es wirklich nur geringfügig und in der Programmlogik eigentlich unbedeutend deswegen meine aufgebrachtheit. Auserdem dokumentiere ich fleißig in PHPDoc

              lgmb

              1. Hallo MB,

                kein Problem. Vielleicht hätte ich das wissen können, wir beide schreiben hier ja schon eine ganze Weile, aber ich habe keine Kladde mit Personenprofilen aller Stammgäste und mein kleiner Kopf schafft das nicht :).

                Rolf

                --
                sumpsi - posui - clusi
          2. Oder, du benutzt PHPDoc-Annotationen, damit wird der Code sogar noch kürzer als deine ursprüngliche Fassung und viele Programme können damit umgehen:

            Ich hab erwähnt das ich öffentliche Methoden die verändert werden können nicht mag. Ich kenn mich, ich renn dann kopflos in irgendwas rein.

            Genau das ist der Punkt, ich hab den Vorschlag gemacht, weil du damit vermeiden kannst, in solche Stolperfallen zu laufen. Nehmen wir mal an, du machst beim Programmieren einen Fehler und weist einer Eigenschaft einen unerlaubten Wert zu:

            $foobar = new FooBar();
            $foobar->fuz= 42; // Defekt: Eigentlich wird hier ein String erwartet.
            

            So wie du die Klasse FooBar implementiert hast, würde der Defekt unbemerkt bleiben. $foobar->foo wäre danach einfach undefiniert. Das nennt sich auch Fail-Silent-System. Das System bleibt stumm, der Fehler bleibt unerkannt.

            Das kann man verbessern, indem man eine Exception in der __set-Methode wirft, wenn der Typ von $value kein String ist. Dann fällt der Fehler auf, sobald man den obigen Code ausführt.

            Mit PHPDoc-Kommentaren, würde schon dein Editor den Rotstift in der Zeile $foobar->fuz = 42; ansetzen und dir mitteilen, dass es da einen Typfehler gibt.

            1. moin,

              Das nennt sich auch Fail-Silent-System. Das System bleibt stumm, der Fehler bleibt unerkannt.

              Danke für den Begriff

              Mit PHPDoc-Kommentaren, würde schon dein Editor den Rotstift in der Zeile $foobar->fuz = 42; ansetzen und dir mitteilen, dass es da einen Typfehler gibt.

              Soweit ich weis kann man bei primitiven un Objekt Typen nur in funktionen und methoden machen:

              function foobar( string $fuz, int $baz, Tok $t ) : array {}
              

              und nicht in Objekt eigenschaften, leider

              class Foobar {
                private string $fuz, int $baz, Tok $t;
              }
              

              Aber es wäre sehr wünschenswert.

              lgmb

              1. Danke für den Begriff

                Immer gerne.

                Mit PHPDoc-Kommentaren, würde schon dein Editor den Rotstift in der Zeile $foobar->fuz = 42; ansetzen und dir mitteilen, dass es da einen Typfehler gibt.

                Soweit ich weis kann man bei primitiven un Objekt Typen nur in funktionen und methoden machen:

                function foobar( string $fuz, int $baz, Tok $t ) : array {}
                

                und nicht in Objekt eigenschaften, leider

                class Foobar {
                  private string $fuz, int $baz, Tok $t;
                }
                

                Richtig, mit nativem PHP geht das nicht. Aber mit PHP + PHPDoc geht das:

                class Foobar {
                
                  /**
                   * @var string
                   */
                  private $fuz
                
                  /**
                   * @var int
                   */
                  private int $baz
                
                  /**
                   * @var Toc
                   */
                  private $t;
                }
                

                PHPDoc-Kommentare werden von Editoren ausgelesen und die können die Informationen für ihre Autovervollständigung und ihre Typchecker verwenden. Wenn das nicht reicht, dann helfen gewöhnliche Getter- und Setter-Methoden, wie in meinem ersten Beispiel. Die dienen nur dazu, den Zugriff auf die privaten Eigenschaften so zu kapseln, dass sie typsicher sind.

                1. moin,

                  Soweit ich weis kann man bei primitiven un Objekt Typen nur in funktionen und methoden machen

                  Richtig, mit nativem PHP geht das nicht. Aber mit PHP + PHPDoc geht das:

                  Das wusste ich nicht. Ich danke dir für den Hinweis

                  lgmb

                2. Hallo 1unitedpower,

                  verkauf nicht zu viel Schlangenöl - bei den Type Hints der Funktionköpfe (die in PHP 7 zu Type Declarations geworden sind) - gibt's von PHP auf die Finger wenn's nicht stimmt. Bei PHPDoc macht nur der Editor oder ein eventueller PHPDoc-fähiger Linter (womit ich nicht PHP -l meine) ein böses Gesicht, dem PHP Interpreter ist das egal.

                  Rolf

                  --
                  sumpsi - posui - clusi
                  1. bei den Type Hints der Funktionköpfe (die in PHP 7 zu Type Declarations geworden sind)

                    Heißen die jetzt nur anders oder gibt es da auch einen semantischen Unterschied? Die Nomenklatur betreffend finde ich Type Declarations fehlgeleitet. Unter einer Typ-Deklaration verstehe ich die Einführung/Bekanntmachung eines neuen/bestehenden Typen, häufig mit einhergehender Typ-Definition. PHPs Type Hints sind aber Annotationen von Werten mit Typen.

                    bei den Type Hints der Funktionköpfe […] gibt's von PHP auf die Finger wenn's nicht stimmt. Bei PHPDoc macht nur der Editor oder ein eventueller PHPDoc-fähiger Linter (womit ich nicht PHP -l meine) ein böses Gesicht, dem PHP Interpreter ist das egal.

                    Gut, dass du es auch nochmal sagst, das kam in meinem letzten Posting wohl nicht so deutlich rüber, wie ich es gerne ausdrücken wollte, indem ich nochmal auf mein erstes Beispiel verwiesen habe.