Ankündigung

Einklappen
Keine Ankündigung bisher.

Objekt auf Getter/Setter Mappen

Einklappen

Neue Werbung 2019

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

  • Objekt auf Getter/Setter Mappen

    Hey,

    Ich bin auf Ideensuche für eine schöne Lösung.
    Über eine Soap API bekomme ich folgendes Array zurück.


    PHP-Code:
    Array
    (
        [
    0] => stdClass Object
            
    (
                [
    payment] => stdClass Object
                    
    (
                        [
    id] => 3
                        
    [name] => Rechnung
                        
    [info] => Bitte beachten SieBei Neukunden [...]
                        [
    info2] => Bitte überweisen Sie uns nach [...]
                    )

                [
    shipping] => stdClass Object
                    
    (
                        [
    id] => 1
                        
    [countryId] => 1
                        
    [name] => DHL Versand
                        
    [tax] => stdClass Object
                            
    (
                                [
    id] => 1
                                
    [mentionId] => 0
                                
    [name] => Mehrwertsteuer (DE)
                                [
    rate] => 19
                            
    )

                    )

                [
    orderProducts] => stdClass Object
                    
    (
                        [
    OrderProduct] => stdClass Object
                            
    (
                                [...]
                            )

                    )

                
                [
    id] => 123456
                
    [orderDate] => 2010-05-13T17:00:00
                
    [contact] => stdClass Object
                    
    (
                        [
    phone] => 1234 56789
                        
    [email] => email@example.com
                    
    )

                [
    billingAddress] => stdClass Object
                    
    (
                        [...]
                    )

                [
    shippingAddress] => stdClass Object
                    
    (
                        [...]
                    )

                [
    isTestOrder] => 
                [
    orderStatus] => stdClass Object
                    
    (
                        [
    id] => 3
                        
    [name] => Per DHL versendet
                    
    )
            )

        [
    1] => stdClass Object
            
    (
                [...]
            )
    [...] 
    Ziel ist es, die einzelnen Bestellungen auf ein vernünftiges Objekt zu Mappen und via Getter darauf zugreifen zu können ohne das Mapping manuell für jeden Key über setOption($option); lösen zu müssen.


    Wenn ich über meiner Foreach definiere wie das Objekt aussieht hab ich in die IDE entsprechende Autovervollständigung für mein Objekt allerdings kann ich dann nur auf die vorhandene Struktur des Objekts zugreifen - welches logischerweise keine Getter vorweisen kann.


    PHP-Code:
    /** @var $oneOrder OrderResult */
            
    foreach ($orders->getOrders() AS $oneOrder){
             echo 
    $oneOrder->id;
            }

    class 
    OrderResult {
        public 
    $id;
        public 
    $orderDate;
        public 
    $isTestOrder;
        public 
    $orderStatus;

    Wünschenswert wäre:
    PHP-Code:
     foreach ($orders->getOrders() AS $oneOrder){
             echo 
    $oneOrder->getId();
            } 
    Da hat doch sicher jemand ne schöne Lösung für.

    gruß roest
    May the Source be with you.


  • #2
    Hallöchen,

    woran scheiterst du nun konkret?

    Viele Grüße,
    lotti

    Kommentar


    • #3
      Hallöchen lottikarotti,

      Ich habe in meiner $oneOrder ja nur das ganz oben gezeigte Objekt.
      Theroretisch müsste ich es um es mit getXY Funktionen erweitern zu können auf ein eigenes Objekt mappen ungefähr so:

      PHP-Code:
      $gutesOrderObjekt = new OrderResult();
      $gutesOrderObjekt->setId($oneOrder->id);
      //[...]

      return $gutesOrderObjekt
      Das würde funktionieren ist aber ne blöde Lösung, da ich in diesem Fall alle (geschätzt) 50 Attribute manuell via setXY() setzen müsste.

      Hast du eine Idee wie man das eleganter Lösen kann?

      //edit: das ganze sollte btw. am Ende ein SDK für eben diese SoapAPI werden.
      May the Source be with you.

      Kommentar


      • #4
        Hallöchen,

        wie wär's mit einem simplen Wrapper?

        PHP-Code:
        class ObjectWrapper{
            
        /**
             * Speichert das Objekt.
             * 
             * @var stdClass
             */
            
        protected $object null;

            
        /**
             * Zugrunde liegendes Objekt injizieren.
             * 
             * @param stdClass $object Das Objekt.
             */
            
        public function __construct(stdClass $object){
                
        /** TODO: Objekt validieren */
                
        $this->object $object;
            }

            
        /**
             * Dieser Getter liefert die Id zurück.
             * 
             * @return integer Die Id.
             */
            
        public function getId(){
                return 
        $this->object->id;
            }

            
        // ..

        Du solltest im Konstruktor oder in den Getter-Methoden natürlich sicherstellen, dass die Eigenschaften auch vorhanden sind.

        Viele Grüße,
        lotti

        Kommentar


        • #5
          Das wird sich so schwer machen lassen, da die Objekte kaum etwas gemeinsam haben. Ich sehe da z.b. in jedem einzelnen stdObject komplett unterschiedliche Inhalte.

          Du solltest am besten anfangen, die Klassen aufzubauen, wie du sie haben willst und dann im __construct() der einzelnen klassen ein stdObject entgegennehmen und dann dort genau das rauziehen, was du brauchst. Das ganze in einer Schleife und du kannst das zumindest ein bisschen reduzieren.
          Lerne Grundlagen | Schreibe gute Beispiele | PDO > mysqli > mysql | Versuch nicht, das Rad neu zu erfinden | Warum $foo[bar] böse ist | SQL Injections | Hashes sind keine Verschlüsselungen! | Dein E-Mail Regex ist falsch

          Kommentar


          • #6
            Jau super tatsächlich ist der Wrapper ein guter Ansatz.

            PHP-Code:
            class OrderResult {
                protected 
            $order;

                function 
            __construct($order){
                    
            $this->order $order;
                }

                public function 
            getId(){
                    return 
            $this->order->id;
                }

               
            /**
               * @return ShippingAdressResult
               */
                
            public function getShippingAddress(){
                    return 
            $this->order->shippingAddress;
                }

            Damit kann ich mir meine Objekte schön manuell aufbauen und dann entsprechend Mappen.

            Der Vollständigkeit halber hier jetzt meine komplette Lösungsstruktur:

            1. (SDK)
            PHP-Code:
                /**
                 * @return Array Array of Orders
                 */
                
            public function getOrders(){
                    
            $orders = array();
                    foreach (
            $this->orders AS $order){
                        
            $orders[] = new OrderResult($order);
                    }
                    return 
            $orders;
                } 
            2. (User)
            PHP-Code:
                    /** @var $oneOrder OrderResult */
                    
            foreach ($orders->getOrders() AS $oneOrder){
                        
            $oneOrder->getId();
                    } 
            May the Source be with you.

            Kommentar


            • #7
              Wenn ich mir die API-Resultate oben ansehe ist der hier empfohlene Wrapper eher ein Facade das Query-Methoden hat und Wrapper liefert.

              Auf welcher Basis erzeugen sich denn die Objekte ? WSDL ? JSON ?
              [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
                Zitat von tr0y Beitrag anzeigen
                Wenn ich mir die API-Resultate oben ansehe ist der hier empfohlene Wrapper eher ein Facade das Query-Methoden hat und Wrapper liefert.
                Ich stehe weiteren Optimierungen offen gegenüber


                Auf welcher Basis erzeugen sich denn die Objekte ? WSDL ? JSON ?
                WSDL
                May the Source be with you.

                Kommentar


                • #9
                  Naja..

                  "Das" Array -> BestellungsIterator mit Query Facade für payment(), shipping() ect., die jeweils PaymentWrapper, ShippingWrapper, ect.. der aktuellen Iterator Position liefern.
                  [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 würde es für die "Unterobjekte" so machen. Entspricht das dem was du meinst?

                    PHP-Code:
                      /** 
                       * @return ShippingAdressResult 
                       */ 
                        
                    public function getShippingAddress(){ 
                            return new 
                    ShippingAdressResult($this->order->shippingAddress); 
                        } 
                    May the Source be with you.

                    Kommentar


                    • #11
                      Ja nur das eine Query-Methode weder ein Getter noch ein Setter ist, entsprechend also keinen get oder set prefix hat.
                      [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


                      • #12
                        Ich bin kein Freund von Klassen, welche Getter- und Setterwälder beherbergen. Auch nicht von einer Vielzahl von Methoden, die alle ähnliche Aufgaben haben.
                        Anstelle von ->getShippingAddress() ist ein Aufruf der Art ->select(' ShippingAddress') auch nicht viel umständlicher. Ist aber auch etwas Geschackssache.

                        Hier mein Ansatz (ohne Fehlerbehandlung und sinnvolle Namen):
                        PHP-Code:
                        class objPars{
                          private 
                        $obj;
                          private 
                        $path = array(
                            
                        'payment_name' => '0/payment/name',
                            
                        'shipping_id' => '0/shipping/id',
                          );
                          
                          public function 
                        __construct($obj){
                            
                        $this->obj $obj;
                          }

                          public function 
                        select($key){
                            
                        $path array_key_exists($key,$this->path
                              ? 
                        $this->path[$key]
                              : 
                        $key;
                            
                        $pathArr explode('/',$path);
                            
                        $r $this->obj;
                            foreach(
                        $pathArr as $k){
                              
                        $r is_array($r) ? $r[$k] : $r->$k;
                            }
                            return 
                        $r;    
                          } 
                        Der Zugriff auf die Werte/Unterobjekte kann per im array definierten Schlüssel oder mit einen kompletten 'Pfad' erfolgen.
                        Dazu ein kleiner Test, die Objektstruktur ist stark vereinfacht:
                        PHP-Code:
                        $a = array(
                          
                        => array(
                           
                        'payment' =>array('id' => 1"name" => "test1"), 
                           
                        'shipping' =>array('id' => 2"name" => "test2"), 
                          )
                        );

                        //Array
                        $wrap = new objPars($a);
                        $v['payment_name'] = $wrap->select('payment_name');
                        $v['payment'] = $wrap->select('0/payment');

                        //Objekt
                        $obj json_decode(json_encode($a));

                        $wrap = new objPars($obj);
                        $v['shipping_id'] = $wrap->select('shipping_id');
                        $v['0/shipping/name'] = $wrap->select('0/shipping/name');

                        //Output
                        var_dump($v); 
                        Ausgabe (mit debugger-Klasse):
                        Code:
                        array (
                          'payment_name' => "test1",
                          'payment' => 
                          array (
                            'id' => 1,
                            'name' => "test1",
                          ),
                          'shipping_id' => 2,
                          '0/shipping/name' => "test2",
                        )
                        LG jspit
                        PHP-Klassen auf github

                        Kommentar


                        • #13
                          Zitat von jspit Beitrag anzeigen
                          Anstelle von ->getShippingAddress() ist ein Aufruf der Art ->select(' ShippingAddress') auch nicht viel umständlicher.
                          2 Gründe, waurm ich sowas total verabscheue

                          - Du hast keine Ahnung, welche Felder es in einer Klasse gibt von außen
                          - Du hast keine Ahnung welcher Datentyp zurückommt, weil du keine PHPDocBlocks machen kannst

                          damit ist das entwickeln mit solchen Klassen ungemein anstrengend, weil du ständig entweder in die Klasse reinschauen musst oder ständig die Doku offen haben musst, um zu wissen, was du überhaupt machen kannst.

                          Mit get/set und DocBlocks kannst du komplett in der IDE entwickeln, da du alle Informationen direkt am Cursor hast.

                          Aber, wems gefällt...
                          Lerne Grundlagen | Schreibe gute Beispiele | PDO > mysqli > mysql | Versuch nicht, das Rad neu zu erfinden | Warum $foo[bar] böse ist | SQL Injections | Hashes sind keine Verschlüsselungen! | Dein E-Mail Regex ist falsch

                          Kommentar


                          • #14
                            Ich stimme ApoY2k hier vollkommen zu.
                            jspit dein Code wäre in diesem Fall überflüssig da ich von der Soap Klasse ja bereits ein Formatiertes + Strukturiertes Array zurückbekomme.

                            Der Aufruf aktuell ohne irgendetwas zu machen wäre ja:
                            PHP-Code:
                            $order->shippingAddress->street 
                            Der klare Nachteil ist aber, dass ich aus der IDE heraus eben nicht weiß welche Objekte und Eigenschaften nun existieren und zurückgegeben werden.
                            Also brauche ich ein SDK welches meine Rückgabe auf hartcodierte Objekte mappt.

                            Dein Code mappt die Objekte zwar wunderbar allerdings Dynamisch - was funktioniert mir aber das Ziel des Mappings nicht erfüllt -> Autovervollständigung durch Verwendung des SDK.

                            Ich verfolge tatsächlich aktuell troys Ansatz nach dieser Struktur:

                            PHP-Code:
                            $order->shippingAddress()->getStreet(); 
                            May the Source be with you.

                            Kommentar


                            • #15
                              Ok, sehe ein, meine Variante ist hier im Thread wohl etwas fehlplatziert.
                              PHP-Klassen auf github

                              Kommentar

                              Lädt...
                              X