Lektion 9.3: Persistente Objekte
Erweiterungen, die eigene Daten speichern, etwa ein Protokoll von Begrüßungen, Abonnements oder Einstellungen pro
Benutzer, brauchen eine Tabelle. eZPersistentObject ordnet eine Tabelle anhand einer einzigen Beschreibung, der
Definition, einer PHP-Klasse zu und übernimmt dann das Speichern, Holen, Zählen und Entfernen von Zeilen; dabei wird
jeder Wert escapt, und es funktioniert auf jeder Datenbank, die Exponential unterstützt. In dieser Lektion legen die
Teilnehmenden eine Tabelle und eine Klasse dafür an.
Hinweis Die Übung legt eine Tabelle an. Führen Sie sie nur auf Ihrer Entwicklungsinstallation aus.
Auf einen Blick
| Kurs | Entwickler |
| Modul | Modul 9: Die Konsole und persistente Objekte |
| Dauer | 60 Minuten (20 Präsentation, 40 Übung) |
| Niveau | Experten |
| Zielgruppe | Entwickler |
| Voraussetzungen | Lektion 9.2; eine Entwicklungsinstallation auf SQLite (der Standard von exp:install) |
Lernziele
Nach dieser Lektion können die Teilnehmenden:
- eine
definition()mitfields,keys,increment_key,class_name,sortundnameschreiben; - neue Zeilen mit
'id' => nullundstore()anlegen; - eine Zeile mit
fetchObject()und viele mitfetchObjectList()holen und mitcount()zählen; - eine Zeile mit
setAttribute()undstore()ändern und mitremove()löschen; - erklären, warum persistente Objekte gegenüber von Hand geschriebenem SQL vorzuziehen sind.
Hinweise für Trainer
So präsentieren Sie es
Quellen: kernel/classes/ezpersistentobject.php (die Definition ist oberhalb von definition() dokumentiert),
Standards für Datenbanken und SQL und
Kernel-Klassen, die sie verwenden, etwa kernel/classes/ezrole.php.
- Die Definition (6 Minuten). Gehen Sie
mysiteGreeting::definition()durch: Jedes Feld hat einenname(den Namen des PHP-Attributs), einendatatype(integer,string,float), einendefaultundrequired;keysist der Primärschlüssel;increment_keywird beim Einfügen von der Datenbank gefüllt;class_nameist die Klasse, zu der die Zeilen werden;nameist die Tabelle. - Neue Zeilen (3 Minuten). Legen Sie sie mit
'id' => nullan, damit die Datenbank die nächste ID vergibt; nachstore()enthältattribute( 'id' )diese ID. Kernel-Klassen wieeZRolemachen es genauso. - Holen (4 Minuten).
fetchObject( $def, null, $conditions )gibt ein Objekt odernullzurück;fetchObjectList( $def, null, $conditions, $sorts, $limit )gibt ein Array zurück; dazucount( $def, $conditions ). Bedingungen sind ein Hash aus Feld und Wert; die Werte werden escapt. - Warum (4 Minuten). Jeder Wert wird für Sie escapt und umgewandelt; derselbe Code läuft auf MySQL, PostgreSQL, SQLite und MongoDB, was bei von Hand geschriebenem SQL nicht der Fall wäre.
- Die Tabelle mitliefern (3 Minuten). Eine echte Erweiterung liefert ihr Schema in
share/db_schema.dba(das Format des Kernels, geschrieben mitezsqldumpschema.phpund geladen mitezsqlinsertschema.php) oder als SQL-Dateien pro Datenbank insql/<engine>/. Im Kurs legt ein kleines Skript die Tabelle auf SQLite an.
Häufige Fragen
Kann sich ein Feldname vom Spaltennamen unterscheiden? Die Schlüssel von fields sind die Spaltennamen; name
ist der Attributname, der mit attribute() verwendet wird. Die meisten Klassen halten beide gleich.
Wie füge ich Methoden wie fetchByName hinzu? Als statische Methoden der Klasse, die fetchObjectList() mit
Bedingungen aufrufen, wie in der Übung.
Transaktionen? Fassen Sie mehrere Schreibvorgänge in $db->begin() und $db->commit() ein (Lektion 9.4).
Stolperfallen
'id' => 0für eine neue Zeile. Eine Null ist ein Wert; geben Sienullan, damit die Datenbank die ID vergibt.- Ein Tabellenname ohne Präfix. Verwenden Sie das Präfix Ihrer Erweiterung (
mysite_), damit Tabellen nie mit denez*-Tabellen des Kernels kollidieren. - Das SQL der Tabelle. Das
CREATE TABLEder Übung ist SQLite-Syntax; MySQL schreibtAUTO_INCREMENT, PostgreSQL verwendetSERIAL. Ein.dba-Schema erspart es, es für jede Datenbank zu schreiben.
Praktische Übung
Auf der Entwicklungsinstallation auf SQLite, in extension/mysite_hello.
Legen Sie
scripts/create_table.phpan, das die Tabelle anlegt, falls es sie noch nicht gibt:// Run once: php bin/php/ezexec.php extension/mysite_hello/scripts/create_table.php (SQLite syntax) $db = eZDB::instance(); $db->query( "CREATE TABLE IF NOT EXISTS mysite_greeting ( id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(100) NOT NULL DEFAULT '', created INTEGER NOT NULL DEFAULT 0 )" ); eZCLI::instance()->output( 'Table mysite_greeting is ready' );Führen Sie es aus:
php bin/php/ezexec.php extension/mysite_hello/scripts/create_table.php.Legen Sie
classes/mysitegreeting.phpan:/** * One stored greeting: a row of the table mysite_greeting. */ class mysiteGreeting extends eZPersistentObject { public static function definition() { return array( 'fields' => array( 'id' => array( 'name' => 'ID', 'datatype' => 'integer', 'default' => 0, 'required' => true ), 'name' => array( 'name' => 'Name', 'datatype' => 'string', 'default' => '', 'required' => true ), 'created' => array( 'name' => 'Created', 'datatype' => 'integer', 'default' => 0, 'required' => true ) ), 'keys' => array( 'id' ), 'increment_key' => 'id', 'class_name' => 'mysiteGreeting', 'sort' => array( 'created' => 'desc' ), 'name' => 'mysite_greeting' ); } public static function create( $name ) { return new self( array( 'id' => null, 'name' => $name, 'created' => time() ) ); } public static function fetch( $id ) { return eZPersistentObject::fetchObject( self::definition(), null, array( 'id' => (int)$id ) ); } public static function fetchByName( $name, $limit = 10 ) { return eZPersistentObject::fetchObjectList( self::definition(), null, array( 'name' => $name ), null, array( 'offset' => 0, 'length' => (int)$limit ) ); } public static function countAll() { return eZPersistentObject::count( self::definition() ); } }Erzeugen Sie die Autoloads neu:
php bin/php/ezpgenerateautoloads.php -e.Legen Sie
scripts/greetings.phpan und führen Sie es mitezexec.phpaus:$cli = eZCLI::instance(); $ada = mysiteGreeting::create( 'Ada' ); $ada->store(); $grace = mysiteGreeting::create( 'Grace' ); $grace->store(); $cli->output( 'Stored IDs ' . $ada->attribute( 'id' ) . ' and ' . $grace->attribute( 'id' ) ); $cli->output( 'Count: ' . mysiteGreeting::countAll() ); $cli->output( 'Named Ada: ' . count( mysiteGreeting::fetchByName( 'Ada' ) ) ); $row = mysiteGreeting::fetch( $grace->attribute( 'id' ) ); $row->setAttribute( 'name', 'Grace H.' ); $row->store(); $cli->output( 'Renamed: ' . mysiteGreeting::fetch( $row->attribute( 'id' ) )->attribute( 'name' ) ); $row->remove(); $cli->output( 'Count after remove: ' . mysiteGreeting::countAll() );Führen Sie das Skript ein zweites Mal aus und vergleichen Sie die IDs.
Ändern Sie
create()auf'id' => 0, führen Sie es einmal aus, lesen Sie das Ergebnis und ändern Sie es wieder zurück.Committen Sie die Klasse und die Skripte.
Erwartetes Ergebnis
- Schritt 2 gibt "Table mysite_greeting is ready" aus.
- Schritt 5 gibt zwei neue IDs, die Anzahl,
Named Ada: 1,Renamed: Grace H.und die Anzahl nach dem Entfernen aus. - Schritt 6: neue, höhere IDs; die Anzahl wächst pro Lauf um eins (Ada bleibt, Grace wird entfernt).
- Schritt 7: Die neuen Zeilen erhalten die ID 0 statt neuer IDs ("Stored IDs 0 and 0"); unter SQLite ersetzt die
zweite die erste. Die Datenbank vergibt IDs nur, wenn die ID
nullist. - Der Trainer lässt alle Teilnehmenden
increment_keyerklären.
Quiz
- Welcher Schlüssel der Definition nennt die Tabelle?
- Welchen Wert muss die ID einer neuen Zeile haben, damit die Datenbank eine vergibt?
A.
0B.nullC.-1D.'' - Welche Methode gibt viele Zeilen zurück, und welche eine Zeile?
- Warum sind persistente Objekte sicherer als SQL-Strings?
- Wie liefert eine Erweiterung das Schema ihrer Tabellen mit?
Antworten
name.- B.
null, wie es Kernel-Klassen wieeZRoletun. fetchObjectList()für viele,fetchObject()für eine.- Werte werden für Sie escapt und umgewandelt, und derselbe Code läuft auf jeder unterstützten Datenbank.
- In
share/db_schema.dba(erzeugt mitezsqldumpschema.php, geladen mitezsqlinsertschema.php) oder als SQL-Dateien pro Datenbank insql/<engine>/.
Weiterführende Literatur
- Standards für Datenbanken und SQL: sicheres SQL, Dialekte, Schemas.
- Datenbankunterstützung: auf welchen Datenbanken Exponential läuft.
- SQLite als Datenbank.
Verwandte Seiten
- Modul 9: Die Konsole und persistente Objekte
- Entwickler: Kursüberblick
- Trainer: hier beginnen
- Freie Dokumentation: Diese Seite darf unter der GNU FDL 1.3 frei kopiert, übersetzt und verbessert werden.
Werden Sie Exponential-Partner
Partner teilen ihre Informationen, stellen Mittel bereit, geben Beiträge zurück und entwickeln die Produkte mit uns, und so wächst Exponential. Eine Partner-Website und ein Dashboard sind für Mitte 2027 geplant: Werden Sie noch heute Partner, damit wir schneller wachsen und neue Funktionen früher liefern.