franz_hoff: Objekteigenschaften in Datenbank speichern

Guten Tag,

ich arbeite mit PHP und möchte gern ein Objekt, genauer gesagt, dessen Eigenschaften in eine Datenbank speichern. Bisher habe ich nur Hinweise gefunden, wie ich das Objekt mittels Serialisierung komplett abspeichern kann. Das ist aber nicht das, was ich will.

Sondern ich möchte bspw. die Eigenschaften $singleBook->title, $singleBook->price und $singleBook->description in der Tabelle 'books' in die zugehörigen Spalten 'title', 'price' und 'description' speichern, damit ich danach mit einem Datenbank-"SELECT ... FROM books WHERE ..." bestimmte Bücher wieder auslesen kann.

Müsste ich da jetzt alle Eigenschaften einzeln in einer INSERT-Anweisung aufführen? Also so "INSERT INTO books (title, price, description) VALUES($this->title, $this->price, $this->description)"?

Oder lässt sich ein Objekt auch eleganter speichern? Also dass automatisch alle Objekteigenschaften auf die entsprechenden Tabellenfelder gemappt werden?

Mir reicht auch gern einfach ein Stichwort, nach dem ich googlen kann.

Mit "PHP objekt datenbank speichern" bzw. der englischen Enstprechung dafür, habe ich nur die Serialisierung gefunden.

Ich denke, mir fehlt eine genau Begrifflichkeit, die ich nicht kenne, mit der die Suche eher zum Erfolg führt.

Danke Franz

  1. Tach!

    Müsste ich da jetzt alle Eigenschaften einzeln in einer INSERT-Anweisung aufführen? Also so "INSERT INTO books (title, price, description) VALUES($this->title, $this->price, $this->description)"?

    Ja, prinzipiell schon.

    Oder lässt sich ein Objekt auch eleganter speichern?

    Naja, du kannst eine Funktion drumherumbauen, die das auf diese Weise erzeugt. Aber von Haus aus hat PHP keinen Mechanismus, dem man lediglich das Objekt gibt und dazu die Eigenschaftsnamen und der macht das für dich.

    Also dass automatisch alle Objekteigenschaften auf die entsprechenden Tabellenfelder gemappt werden?

    Natürlich musst du das vorgenannte nicht nochmal selbst erfinden, denn ORMs (Objekt-Relation-Mapper) gibt es bereits.

    Bedenke aber, dass das eine Zwischenschicht ist, die Ausführungszeit braucht. Das lohnt sich erst in Projekten bestimmter Größenordnung richtig, weil die eingesparte Programmiererzeit wichtiger ist als mehr Power im Server.

    dedlfix.

    1. Vielen Dank für die schnelle Antwort.

      Und es sieht so aus, dass "Objekt-Relation-Mapper" der Begriff ist, den ich gebraucht habe 😀

      Ein schönes Wochenende dir!

      1. Hallo,

        und bevor du dir selbst eins entwickelst, empfehle ich dir noch Doctrine ORM.

        Das ist wohl das größte und bekannteste ORM. Lass dich davon nicht erschlagen, es ist nicht ganz trivial. Aber es lohnt sich, sich damit zu beschäftigen.

        Viele Grüße Matti

  2. hi,

    Müsste ich da jetzt alle Eigenschaften einzeln in einer INSERT-Anweisung aufführen? Also so "INSERT INTO books (title, price, description) VALUES($this->title, $this->price, $this->description)"?

    Korrekt!

    Eleganter.. Also dass automatisch alle Objekteigenschaften auf die entsprechenden Tabellenfelder gemappt werden?

    Bei diesem Tabellendesign würde ich von einer Automatisierung absehen. Denn erstens notierst Du das INSERT Statement sowieso nur einmal (prepared), zweitens bleibt es leserlich und drittens bist Du bei etwaigen Änderungen ruckzuck fertig. MFG

  3. Tach!

    Müsste ich da jetzt alle Eigenschaften einzeln in einer INSERT-Anweisung aufführen? Also so "INSERT INTO books (title, price, description) VALUES($this->title, $this->price, $this->description)"?

    Nachtrag: So geht "SQL-Statement" natürlich nicht. Da fehlt die kontextgerechte Behandlung der Werte. Oder aber die Verwendung von Prepared Statements.

    dedlfix.

    1. Nachtrag: So geht "SQL-Statement" natürlich nicht. Da fehlt die kontextgerechte Behandlung der Werte. Oder aber die Verwendung von Prepared Statements.

      Yepp!

      Ich verwende generell Prepared Statements.

      Danke aber für den Hinweis!

  4. Müsste ich da jetzt alle Eigenschaften einzeln in einer INSERT-Anweisung aufführen? Also so "INSERT INTO books (title, price, description) VALUES($this->title, $this->price, $this->description)"?

    Ich denke, mir fehlt eine genau Begrifflichkeit, die ich nicht kenne, mit der die Suche eher zum Erfolg führt.

    get_object_vars() hilft Dir schon mal dabei, herauszufinden, welche Eigenschaften ein Objekt hat.

    Hier mal der Schnellschrieb, der (siehe Hinweise unten, außer zu Testzwecken) nicht übernommen werden kann:

    <?php
    
    class foo {
        public $a;
        public $b;
        public $c;
        
        function __construct( $a, $b, $c )  {
    		$this -> a = intval( $a );
    		$this -> b = floatval( $b );
    		$this -> c = trim( $c );
    		#$this ->DBH = mysqli_connect("host", "user", "password", "base");
        }
    
        function safeInDatabase() {
        
    		$ar = array_keys( get_object_vars( $this ) );
    		$colums=[];
    		$values=[];
    		
    		foreach ( $ar as $key )  {
    		    if ('DBH' != $key ) {
    				    $colums[] = '`' . $key . '`';
    				    $type = gettype ( $this -> $key );
    				    if     ( 'double'  == $type ) { $values[] = $this -> $key; }
    				    elseif ( 'integer' == $type ) { $values[] = $this -> $key; }
    				    elseif ( 'boolean' == $type ) { $values[] = $this -> $key; }
    				    #elseif ( 'string' == $type ) { $values[] = mysqli_real_escape_string( $this -> DBH,  $this -> $key ); }
    				    elseif ( 'string' == $type ) { $values[] = '"' . str_replace( '"', '\"',  $this -> $key ) . '"'; }
    			 }
    		}
    		$sql  = 'INSERT INTO `foo` ('
    			  .  implode(',',  $colums )
    		      . ') VALUES ('
    		      .  implode(',',  $values )
    		      . ');';
    		return $sql;
        }
    
    }
    
    $test = new foo( 42, 4.2, "Restaurant" );
    echo $test-> safeInDatabase();
    

    Resultat:

    INSERT INTO `foo` (`a`,`b`,`c`) VALUES (42,4.2,"Restaurant");
    

    Man kann den SQL-String an die Datenbank schicken, freilich auch das Binding durchführen, statt den String erst zurück- und dann auszugeben. Ebenso kann man natürlich das Verbindungsobjekt global nutzen, PDO benutzen und tausend andere Teile davon auf tausend andere Arten erledigen und sich natürlich gegen alle Fehler absichern, sogar die Tabelle darauf prüfen, ob die Spalten überhaupt existieren...

    1. Hallo ursus,

      das zeitweilige Minus war von mir, ich habe nicht richtig hingeschaut. Darum ist es wieder weg. Sorry.

      Als generische Reflection-Lösung ist das nicht schlecht, allerdings hatte der OP auch geschrieben, dass er nicht alle Attribute mappen will. Deswegen halte ich die Reflection-Lösung hier für suboptimal. Besser wäre - meiner Meinung nach - ein generischer SQL Builder, dem Du einen Satz Spaltennamen und Werte vor die Füße kübelst und der daraus ein INSERT Statement baut.

      Übrigens bin ich der Meinung, dass man es sich gar nicht erst angewöhnen sollte, Stringliterale in einem SQL Statement in "Anführungszeichen" zu setzen. Der Standard-Delimiter für ANSI SQL Stringliterale ist das 'Hochkomma'. Es gibt in MYSQL und auch MSSQL Schalter, die "Literale" erlauben, aber eigentlich verwendet man diese Notation für Tabellen- oder Spaltennamen, die Sonderzeichen enthalten. Also das, wofür MYSQL auch den `Backtick` anbietet und MSSQL die [eckigen Klammern].

      Meine Idee, wie man einen SQL Builder einsetzen könnte:

      function saveInDatabase() {
         SQLBuilder::createInsert('books', [
            "title" => $this->DBH->escape_string($this->title),
            "price" => $this->DBH->escape_string($this->title),
            "description" => $this->DBH->escape_string($this->description)
         ]);
      }
      

      Wenn man an diesem Punkt ist, fragt man sich natürlich, warum man überhaupt das DB-Handle im Datenobjekt hat, eigentlich weiß der SQL Builder damit viel mehr anzufangen. Warum nicht gleich einen SQL Handler draus machen? Das ist jetzt auch ein Schnellschrieb zur Veranschaulichung, keine Garantie auf Funktion :)

      function saveInDatabase() {
         SQLHandler::insert('books')
           ->AddString('title', $this->title)
           ->AddNumber('price', $this->price)
           ->AddString('description', $this->description)
           ->execute();
      }
      

      Ich bin ein Fan von verkettbaren APIs. Man baut das so, dass SQLHandler::insert() ein Objekt erzeugt, das den Insert erzeugen kann. Dieses Objekt hat Methoden, die die Daten ergänzen und das Objekt wieder zurückgeben. Dadurch kann man die Aufrufe verketten. Der letzte Aufruf erzeugt dann den INSERT und führt ihn auch gleich aus.

      class SQLHandler {
         public static $DB;   // Hier das MYSQLI-Objekt speichern
         public static function insert($DB, $table) {
            return new SQLInsertFactory($table);
         }
      }
      
      class SQLInsertFactory {
         private $db;
         private $table;
         private $columns;
         private $values;
      
         public function __construct($db, $table) {
            $this->db = $db;
            $this->table = $table;
            $this->columns = [];
            $this->values = [];
         }
      
         private function addColumnAndValue($col, $val) {
            array_push($this->columns, "`$col`");
            array_push($this->values, $val);
         }
      
         public function AddString($col, $val) {
            $this->addColumnAndValue($col, "'".$db->escape_string($val)."'");
            return $this;
         }
      
         public function AddNumber($col, $val) {
            $this->addColumnAndValue($col, floatval($val));
            return $this;
         }
      
         public function execute() {
            $sql = "INSERT INTO `$this->table` ("
                  . implode(", ", $this->columms)
                  . ") VALUES ("
                  . implode(", ", $this->values) . ")";
            return $this->db->query($sql);
         }
      }
      

      Sowas kann man noch ausfeilen zu einem InsertOrUpdate, mit Zusatzmethoden um die Key-Columns für den Update zu definieren. Die üblichen CRUD-Statements kann man damit generisch erzeugen.

      Und wenn man irgendwann von mysqli auf mssql oder postgre wechseln will, lädt man bloß einen anderen SQLHandler ins Projekt.

      Rolf

      --
      sumpsi - posui - clusi
      1. hi,

        Du hast Feldnamen und Werte in 2 verschiedenen Arrays. Das ist schlecht in Hinsicht auf Datenkonsisenz. Deswegen ja mein Hinweis auf den Hashslice was mit Perl möglich ist: Da bleibt das nämlich schön zusammen und man braucht nur noch 1 Array mit den Feldnmamen.

        Gibt es in PHP keine verleichbare Arrayfunktion? MFG

        1. Hallo pl,

          doch, hätte ich machen können, wäre vermutlich sogar einfacher gewesen. Mein Einstiegsbeispiel verwendet das.

          Mein c# Background, in dem es „sortierte Dictionarys“ nicht gibt, hat da zugeschlagen.

          Rolf

          --
          sumpsi - posui - clusi
          1. Der Hash Slice Hack in Perl geht so, daß anstelle eines Wertes für einen Schlüssel ein Array von Werten für ein Array von Schlüsseln geliefert wird. Und zwar in genau derselben Reihenfolge. Aber offensichtlich gibt es sowas in PHP gar nicht. Für DB Anwendungen jedenfalls ist sowas ungemein praktisch. MFG

            1. Tach!

              Der Hash Slice Hack in Perl geht so, daß anstelle eines Wertes für einen Schlüssel ein Array von Werten für ein Array von Schlüsseln geliefert wird. Und zwar in genau derselben Reihenfolge. Aber offensichtlich gibt es sowas in PHP gar nicht. Für DB Anwendungen jedenfalls ist sowas ungemein praktisch.

              Die Daten stecken in einem Objekt. Wenn nur ein paar Felder davon genommen werden sollen, müsste man einen Objekt-Slice erstellen oder das Objekt erst in ein Array konvertieren, um davon dann einen Teil herauszunehmen. So nett ein Array-Slice auch wirken mag, muss man hier also erst die Gegebenheiten anpassen, um es überhaupt nutzen zu können.

              Wenn es lediglich darum geht, eine Liste von Eigenschaftsnamen (als Magic Strings) anzugeben, dann kann man das auch als Array of Strings tun und es der aufgerufenen Funktion überlassen, über diese zu iterieren und die entsprechenden Daten aus dem Objekt für das Statement zu besorgen. Die Daten als einen Ausschnitt aus einem Array vorliegen zu haben, um dann lediglich mit einem Join zusammenzufügen, mag verlockend aussehen. Aber zum einen ist einen Liste von Eigenschaften anzugeben nicht aufwendiger als eine solche Liste für einen Array-Slice zu notieren. Zum anderen ist ein simples Join als Folgeverarbeitung nicht ausreichend, weil es den Kontextwechsel unberücksichtigt lässt. Da müsste man bei der Verarbeitung des Slices etwas mit Callback haben, um den Wert korrekt maskieren zu können.

              Da halte ich es für einfacher und flexibler eine simple Schleife über das Array der Eigenschaftsnamen durchzulaufen. Letzten Endes ist das Join in Verbindung mit dem Array-Slice nur Syntactic Sugar, der in diesem Fall noch dazu ein unbrauchbares Ergebnis liefert, wenn man daraus ein herkömmliches SQL-Statement erzeugt.

              Der Array-Slice-Voschlag berücksichtigt zudem auch nicht, dass die RolfB-Methode ein maßgeschneidertes Vorgehen für die verschiedenen Datentypen ist, die man auch problemlos um weitere Dinge ergänzen kann, zum Beispiel eine Prüfung des tatsächlichen Datentypes oder eines Wertebereiches.

              dedlfix.

              1. Tach!

                Der Hash Slice Hack in Perl geht so, daß anstelle eines Wertes für einen Schlüssel ein Array von Werten für ein Array von Schlüsseln geliefert wird. Und zwar in genau derselben Reihenfolge. Aber offensichtlich gibt es sowas in PHP gar nicht. Für DB Anwendungen jedenfalls ist sowas ungemein praktisch.

                Die Daten stecken in einem Objekt. Wenn nur ein paar Felder davon genommen werden sollen, müsste man einen Objekt-Slice erstellen oder das Objekt erst in ein Array konvertieren, um davon dann einen Teil herauszunehmen. So nett ein Array-Slice auch wirken mag, muss man hier also erst die Gegebenheiten anpassen, um es überhaupt nutzen zu können.

                Genau so eine Funktion würde ich mir schreiben. Denn das ist das Eigentliche worauf es ankommt und das war ja auch das ursprüngliche Anliegen Also dass automatisch alle Objekteigenschaften auf die entsprechenden Tabellenfelder gemappt werden?

                PHP's get_object_vars() ist leider nicht die Lösung. Guck Dir meinen Perlcode an da kannst Du was lernen.

                MFG

                1. Tach!

                  PHP's get_object_vars() ist leider nicht die Lösung. Guck Dir meinen Perlcode an da kannst Du was lernen.

                  Nein, ich kann daraus nichts lernen, weil ich ihn nicht in allen Einzelheiten verstehe. Es reicht nicht, einfach nur Perlcode hinzuwerfen, wenn PHP das Thema ist. Die Syntax von Perl ist zu speziell, als dass man das problemarm verstehen würde. Ich sehe zudem nicht, dass Perl mir irgendwas gibt, was ich nicht bereits mit den mir bekannten Programmiersprachen erledigen kann.

                  Das was ich aber in deinem Posting sehe, ist fachlich nichts neues für mich. Ich sehe aber auch, dass du dich mal wieder überschätzt, was die Nützlichkeit deiner Antwort für das gegebene Thema angeht.

                  dedlfix.

                  1. Tach!

                    PHP's get_object_vars() ist leider nicht die Lösung. Guck Dir meinen Perlcode an da kannst Du was lernen.

                    Nein, ich kann daraus nichts lernen, weil ich ihn nicht in allen Einzelheiten verstehe.

                    Hab ich doch erklärt: Der Code macht ein Insert genau mit den Feldnamen die vorliegen bzw. vorgegeben sind. Und das ist das worauf es bei Datenbankanwendungen ankommt. Deswegen wird im DB Design ein Default definiert und ein erweitertes INSERRT Statement notiert. Erweitert heißt: Es werden die Feldnamen aufgeführt.

                    Wenn Eigenschaften/Felder fehlen sollten

                    my %book = ( 
                      isbn => "12-34", 
                      author => 'Max-Heinrich Schramm', 
                      title => 'Der Weg war völlig umsonst' 
                    );
                    %book = ( author => 'Martin Selber', title => 'Mit Spule Draht und Morsetaste' );
                    

                    Schlägt das Statement nicht fehl, weil vorher mit keys %book die Felder ermittelt werden und damit das Statement präpariert wird.

                    Aber Du hast schon recht, den PerlCode brauchen wir hier nicht, weil es darauf ankommt die Idee zu verstehen! MFG

    2. Nur am Rande: In Perl gibt es den Hash Slice womit man Feldnamen mit den dazugegörigen Values zweckmäßig verbindet:

      @fields = qw(isbn author year);     # Feldnamen, Eigenschaften
      my @qm = map{"?"}1..scalar @fields; # Platzhalter f. Insert
      $dbh->do(qq(
         insert into books (@{[join ',', @fields]}) values(@{[join ',', @qm]})
       ),{}, @book{"@fields"});
      

      Womit man das Array mit den Feldnamen/Eignschaften zentral halten kann. Wichtig ist es, in der Tabelle Defaultwerte zu setzen insbesondere bei Erweiterungen. Ansonsten hat man nur noch ein Array was im Code bei Veränderungen anzupassen wäre.

      1. Hallo pl,

        Nur am Rande: In Perl […]

        Es geht hier um PHP. Bitte hör auf ständig auf deinen Perl-Scheiss hinzuweisen. Danke.

        LG,
        CK

        1. Scheiss

          Ich habe gerade geschaut, ob Google heute ein besonderes Doodle hat. Hab keines gesehen, ganz normales Logo. Fazit: Heute ist, entgegen der von Dir erzeugten Vermutung, nicht der international ausgerufene "Schlechte-Laune-Samstag".

          1. Hallo ursus,

            meine Wortwahl hier war bewusst und mit Absicht. Ich habe keine Lust mehr, bei jedem Thread PLs Unsinn und Getrolle – kurz: scheiss – zu lesen.

            LG,
            CK

            1. meine Wortwahl hier war bewusst und mit Absicht.

              Um so schlimmer.

              1. Hallo ursus,

                Bezug nehmend auf deine Überschrift: meine Laune ist nicht schlecht. Es reicht einfach nur. Das Maß ist voll.

                LG,
                CK

                1. meine Laune ist nicht schlecht.

                  Nun. Deine Wortwahl vermittelt - mit allem Verlaub - den gegenteiligen Eindruck.

                  Ich bin so guter Dinge,
                  So heiter und rein,
                  Und wenn ich einen Fehler beginge,
                  Könnt's keiner sein.
                  

                  Johann Wolfgang von Goethe

                  1. Hallo ursus,

                    ich weiß nicht, was du mir in diesem Zusammenhang sagen möchtest.

                    Ich erkläre nochmal, warum meine Wortwahl so ausfiel: PL äußert sich zu beinahe jedem Thread hier im Forum, wahlweise entweder mit Unsinn, mit politisch extremen Ansichten (wahlweise faschistisch oder eher im linken extremen Sprektrum), mit Verschwörungstheorien und manchmal mit tatsächlich sinnvollen Beiträgen.

                    Das habe ich mir jahrelang angeschaut. Das ging sogar soweit, dass mir ernsthaft die Lust flöten gegangen ist mich überhaupt noch zu beteiligen (siehe auch meine stark gesunkene Posting-Frequenz).

                    Ich habe die Schnauze voll. Wenn ich sowas sehe, gebe ich jetzt kontra, und das auch deftig. Das muss dir nicht gefallen, ist mir dann aber auch egal.

                    Für mich ist hier auch Ende der Diskussion.

                    LG,
                    CK

                    1. ich weiß nicht, was du mir in diesem Zusammenhang sagen möchtest.

                      Ich glaube nicht, dass der für die Durchsage benutzte Blumenstrauß für Dich zu dicht ist.

                      Möglicherweise hilft es in solchen Situationen, sich etwas Zeit zu lassen und erst mal etwas ganz anderes zu tun. Ich denke, die "Primeldichte" ist im vorstehenden Satz auf einem Maß angelangt, welche es zulässt, dass jeder auch nur halbwegs verständige und aufmerksame Leser weiß was ich meine.

                    2. Hallo, Christian,

                      ich möchte dir vollkommen recht geben, auch wenn ich zu einem anderen Schluss gelangt bin. Ich habe für mich entschieden, dass pl meine Zeit nicht wert ist - er hat wiederholt bewiesen, dass ihm meine Zeit (die ich in Antworten an ihn gesteckt habe) auch egal ist.

                      Meine passiv-aggressive Herangehensweise an ihn scheint auf jedenfall nicht erfolgreich zu sein. Wer weiß, vielleicht freut er sich ja auch, dass er wieder jemanden aus dem Forum vergrault hat? Und daher möchte ich dir sagen, dass ich deine Vorgehensweise begrüße.

                      Viele Grüße Matti

                      1. Und daher möchte ich dir sagen, dass ich deine Vorgehensweise begrüße.

                        Nein, nicht.

                        „Die Gesetzgebung ist an die verfassungsmäßige Ordnung, die vollziehende Gewalt und die Rechtsprechung sind an Gesetz und Recht gebunden.“

                        Das ist das „Rechtsstaatsprinzip“ aus dem Grundgesetz, welches kluge Köpfe einst einführten, weil diese nicht damit damit einverstanden waren, dass es zwar prinzipiell Gesetze gab, diese aber die Mächtigen nicht banden.

                        Wenn das also kluge Köpfe waren, dann kann es keine gute Idee sein, einerseits …

                        Dieser Beitrag ist unkonstruktiv oder provokativ und trägt zu einer Verschlechterung der allgemeinen Stimmung im Forum bei.

                        … als Sperrgrund zu notieren und andererseits selbst so zu formulieren wie es Christian in einem „Haudraufmoment“ getan hat. Denn solches Handeln ist nicht nur provokativ sondern vorliegend auch das Paradebeispiel von "Ich mach die Regeln, halte mich aber selbst nicht daran!" und insofern (sic: und durch die Vorbildwirkung!) trägt es auch zur "Verschlechterung der allgemeinen Stimmung im Forum" bei.

                      2. Tach!

                        ich möchte dir vollkommen recht geben, auch wenn ich zu einem anderen Schluss gelangt bin. Ich habe für mich entschieden, dass pl meine Zeit nicht wert ist - er hat wiederholt bewiesen, dass ihm meine Zeit (die ich in Antworten an ihn gesteckt habe) auch egal ist.

                        Ich empfinde ähnliches. Was aber ist mit denen, die seine Antworten nicht beurteilen können. Sollen wir seine Postings einfach unkommentiert im Forum stehen lassen? Auf dass seine Unkenrufe die Qualität des Forums betreffend sich durch seine Postings von selbst bestätigen?

                        Meine passiv-aggressive Herangehensweise an ihn scheint auf jedenfall nicht erfolgreich zu sein. Wer weiß, vielleicht freut er sich ja auch, dass er wieder jemanden aus dem Forum vergrault hat? Und daher möchte ich dir sagen, dass ich deine Vorgehensweise begrüße.

                        Prinzipiell ja, aber mit der Wortwahl bin ich nicht einverstanden. Man macht sich damit nur selbst angreifbar, wenn man sich auf so ein Niveau begibt.

                        Vielleicht ist es an der Zeit, die Konsequenzen aus seinem immer wieder gezeigten (gelinde gesagt) Unwillen der Zusammenarbeit zu ziehen und seine Postings nur noch mit dem Löschknopf zu kommentieren.

                        dedlfix.

          2. Hi Jörg,

            WIR lassen UNS doch nicht von irgendwelchen HONKs die Laune verderben. DIE sollen doch erstmal zeigen was SIE draufhaben, aber wahrscheinlich kommt da eh nicht viel bis gar nüscht.

            Schönes Wochenende Dir (und mir natürlich)!

            PS: Was Perl DBI betrifft, das ist ein Blick übern Tellerrand den sich jeder PHP Programmierer, der sich ernsthaft mit dem Thema Datenbankanbindung befasst, mal antun sollte. Ansonsten bleiben die halt in ihrer Wurstsuppe auf der sie dahergeschwommen kommen.

            --
            HONK: Hilfskraft Ohne Nennenswerte Kenntnisse
            1. Ich hatte gehofft, dass Du dazu schweigst. Ich weiß allerdings auch SEHR GENAU wie schwer das ist.

              "HONKs", "HONK: Hilfskraft Ohne Nennenswerte Kenntnisse", "Wurstsuppe", "erstmal zeigen was SIE draufhaben".

              Das war jetzt zwar Deine Meinung, aber in Hinsicht auf mein Ansinnen ist ausgerechnet Deine Wortwahl nicht hilfreich. Auch ist einiges davon inhaltlich nicht vertretbar: CK hat was drauf: Er hat immerhin mindestens dieses Forum programmiert.

              Du willst nicht, dass man Dich beleidigt? Dann ruf einfach nicht in den Wald. Auch nicht als Entgegnung, falls Du das als solche verstanden haben willst.

              Ja, auch Dir ein schönes Wochenende.

  5. Oder lässt sich ein Objekt auch eleganter speichern? Also dass automatisch alle Objekteigenschaften auf die entsprechenden Tabellenfelder gemappt werden?

    Undefiniert viele Eigenschaften sollte man nicht in Feldern speichern.

    Lang ists her, da habe ich ein Konzept für Smartphones entwickelt. Genauer: Das Finden geeigneter Modelle aufgrund von geforderten Eigenschaften.

    Smartphones sind Objekte mit ungezählten Eigenschaften und ständig kommen Eigenschaften hinzu bei neuen Smartphones.

    Ich brauche dazu drei Tabellen:

    • Smartphone-Modelle
    • Eigenschaften
    • Verknüpfung Modelle - Eigenschaften n:n

    Der suchende Kunde kann nun beliebig viele Eigenschaften markieren (checkbox) und dann die Modelle mit Beschreibung sehen.

    Ist es das, was du suchst?

    EDIT: Das System kam nicht zum Einsatz, weil der Handel Kaufentscheidungen per Bauchgefühl möchte.

    1. Das System kam nicht zum Einsatz, weil der Handel Kaufentscheidungen per Bauchgefühl möchte.

      Das ist schlicht wahr. Allerdings sehe ich mich immer mehr in der Situation, dass ich einen Kauf NICHT tätige, wenn ich über die mich interessierenden Eigenschaften NICHT informiert werde. In manchen Märkten packe ich eiskalt aus um an die Produktbeschreibung zu kommen oder mir das Gerät anzusehen…

      Was jetzt Deinen Beitrag betrifft wüsste ich zu gern was daran den Mausklick beförderte. Kann nichts daran finden - vermutlich hat sich jemand schlicht verklickt.

      1. Hallo ursus,

        ich war's nicht, aber auf die Frage nach ORM mit einem Beispiel für ein EAV-Tabellendesign zu antworten passt nicht so ganz.

        Rolf

        --
        sumpsi - posui - clusi
        1. aber auf die Frage nach ORM mit einem Beispiel für ein EAV-Tabellendesign zu antworten passt nicht so ganz.

          Ja. Aber wenn man plötzlich jeden Blick durch die Glaskugel (Hier nach dem Motto: "Was willst Du eigentlich wirklich?") abstrafen wöllte, dann ist das ebenfalls daneben. Ich denke Linuchs wollte ein Beispiel dafür geben, wie man ein solches Konstrukt vermeiden könnte. Und für manchen (ich zähle dazu) ist ein Beispiel aussagekräftiger als "tausend Worte", die bei manchem "mangels verständlicher Wörter" oft auch nur als "Geblahfasel" ankommen.

          Die Ausgangsfrage war ja, zusammengekürzt diese:

          ich arbeite mit PHP und möchte gern ein Objekt, genauer gesagt, dessen Eigenschaften in eine Datenbank speichern. Bisher habe ich nur Hinweise gefunden, wie ich das Objekt mittels Serialisierung komplett abspeichern kann. Das ist aber nicht das, was ich will.

          und, vor allem:

          Oder lässt sich ein Objekt auch eleganter speichern? Also dass automatisch alle Objekteigenschaften auf die entsprechenden Tabellenfelder gemappt werden?

          Das lässt, im Hinblick auf ungenaue und teils sogar unrichtige Problemdarstellungen einer Vielzahl anderer Fragender unter anderem durchaus die (wohl) von Linuchs getroffene Spekulation zu, dass der TO auch beliebige, vorher nicht (zum Zeitpunkt des Programmierens also unbekannte) Eigenschaften abspeichern will. Linuchs schreibt ja (wohl) deshalb auch "Undefiniert viele Eigenschaften sollte man nicht in Feldern speichern."

          Wenn da schon mit negativ bewertet wird, dann geht die Stimmung hier vor die Hunde, weil sich im Hinblick auf anonyme negative Bewertungen mit allenfalls geringfügigster, vorliegend sogar fragwürdiger und vor allem gar nicht gegebener gelieferter Rechtfertigung keiner mehr antwortet.

          Nachtrag:

          Wie ich gerade sehe ist die negative Bewertung "spurenfrei" weg. Danke!

    2. Tach!

      Oder lässt sich ein Objekt auch eleganter speichern? Also dass automatisch alle Objekteigenschaften auf die entsprechenden Tabellenfelder gemappt werden?

      Undefiniert viele Eigenschaften sollte man nicht in Feldern speichern.

      Wenn es denn undefiniert viele sind. Aber undefiniert viele würde ich auch nicht als Eigenschaften von Objekten modellieren wollen. Undefinierte Werte ist besser in Key-Value-Arrays (assoziative Arrays, Dictionarys) aufgehoben. Der Unterschied ist, dass die Namen von Objekteigenschaften Identifier sind, die genau bekannt sind, und damit sind sie auch vom Code direkt ansprechbar. Ein Array ist eine Sammlung mit praktisch unbegrenzter Anzahl von Elementen, deren Keys aber auch zur Entwicklungszeit unbekannt sein können. Ja, Objekt in PHP können ebenfalls zur Laufzeit beliebig viele Eigenschaften dazubekommen, doch das ergibt nur einen Haufen Probleme. Da man ja nicht weiß, welche der Eigenschaften es sind, ist es schwierig, die festen von den variablen Eigenschaften zu trennen, vor allem, wenn man über lediglich letztere iterieren möchten. Ja, Iterieren über Objekteigenschaften geht grundsätzlich, ist aber letztlich nur ein Notbehelf. Um die variablen Eigenschaften ansprechen zu können, braucht man variable Variablen, aber dann kann man auch gleich einen Array-Zugriff nehmen. Variable Objekteigenschaften bieten keinen allgemeinen Vorteile gegenüber Arrays.

      Ich brauche dazu drei Tabellen:

      • Smartphone-Modelle
      • Eigenschaften
      • Verknüpfung Modelle - Eigenschaften n:n

      Das typische EAV-Modell. Aber im vorliegenden Fall ging es wohl nicht um beliebig viele unbekannte Eigenschaften, sondern um Objekte mit bekannten Eigenschaften und nur um einen einzelnen Mechanismus, der diese nicht zu kennen braucht, weil er generisch gestaltet werden soll.

      Ist es das, was du suchst?

      EAV hat seinen großen Auftritt, wenn es sich zur um erst zur Laufzeit bekannte Eigenschaften handelt. Doch EAV ist kein Allheilmittel. Man wird auch erheblichen nachteiligen Aufwand feststellen, wenn es für bekannte Strukturen verwendet werden soll. Referenzielle Integrität lässt sich zum Beispiel damit nicht vom DBMS sicherstellen. Die Eigenschaftsnamen sind Magic Strings. Hat man den richtigen String, passiert zur Laufzeit das richtige. Aber zur Entwicklungszeit kann man das nicht durch statische Code-Analyse überwachen. EAV hat sich nicht ohne Grund nicht als das allein seelig machende Speichermodell etabliert.

      dedlfix.

      1. Hallo,

        Ich brauche dazu drei Tabellen:

        • Smartphone-Modelle
        • Eigenschaften
        • Verknüpfung Modelle - Eigenschaften n:n

        Das typische EAV-Modell.

        So wie ich EAV bisher begriffen habe, wird dabei eine Tabelle mit drei Spalten verwendet. Nicht aber wie Linuchs vorschlägt 3 Tabellen.

        Gruß
        Kalk

        1. Tach!

          Ich brauche dazu drei Tabellen:

          • Smartphone-Modelle
          • Eigenschaften
          • Verknüpfung Modelle - Eigenschaften n:n

          Das typische EAV-Modell.

          So wie ich EAV bisher begriffen habe, wird dabei eine Tabelle mit drei Spalten verwendet. Nicht aber wie Linuchs vorschlägt 3 Tabellen.

          Du meinst das, was Linuchs als die dritte aufgeführt hat, das V. Aber man braucht schon noch die erste Tabelle als die, die das Ding beschreibt, dessen Eigenschaftswerte in Tabelle 3 stehen. Fachbegriff für das Ding ist Entität, also E. Und Tabelle 2 braucht es, um die Eigenschaften mit deren Metadaten zu verwalten, also A.

          Man kann zur Not auf A verzichten, muss dann aber immer Tabelle V scannen, um alle Eigenschaftsnamen zu erhalten. Aber das wird dann noch unhandlicher, als das EAV-Model schon ist.

          In der Praxis sieht es sogar noch so aus, dass man mitunter mehrere V-Tabellen hat, je Datentyp eine, damit man nicht alle Nicht-Strings serialisieren oder als Literal speichern muss. Daraus ergibt sich meist auch, mehrere A-Tabellen zu haben, um die referenzielle Integrität mit Fremdschlüssel-Beziehungen sicherstellen zu können.

          dedlfix.