HACK SQL-Anweisungen für Datenbanken automatisch erzeugen HACK #41 SQL-Anweisungen für Datenbanken automatisch erzeugen Hack #41 Verwenden Sie PHP, um aus einem Datenbankschema im XML-Format automatisch SQL-Skripten zu erstellen. Eines der am häufigsten auftretenden Probleme beim Schreiben von Datenbankcode tritt auf, wenn die PHP-Anweisungen nicht mehr mit der Datenbankstruktur zusammenpassen oder umgekehrt. Normalerweise haben wir ein .sql-Skript, um die Datenbank mit den benötigten Tabellen und Daten zu füllen. Es kann allerdings sehr schwer sein, dieses Skript immer auf dem neuesten Stand zu halten, besonders wenn Sie gleichzeitig auch den PHP-Code, der auf die Tabellen zugreift, aktualisieren müssen. Dieser Hack zeigt Ihnen ein paar einfache Skripten, mit denen Sie anhand einer XML-basierten Datenbankbeschreibung die nötigen SQL- und PHPSkripten automatisch erstellen können. Auf diese Weise ist sichergestellt, dass SQL- und PHP-Code aufeinander abgestimmt bleiben. Und selbst wenn Sie Ihren Datenbankserver oder die PHP-Version wechseln, können Sie immer noch die gleiche schema.xml-Datei verwenden. Sie brauchen nur den Generator so anzupassen, dass er den entsprechenden Code ausgibt. In Abbildung 5-5 sehen Sie den Programmfluss. Hierbei wird die Datei schema.xml als Eingabe für den Generatorencode (in PHP geschrieben) verwendet, der die MySQL-Datei erzeugt, die dann zum Anlegen der Datenbank verwendet wird. schema.xml gen.php db.sql Abbildung 5-5: Der Generator zum Erzeugen von SQL aus einem im XML-Format gespeicherten Schema Der Code Speichern Sie Beispiel 5-25 mit der XML-Beschreibung einer Datenbank als schema.xml ab. Beispiel 5-25: XML-Beschreibung einer Datenbank <schema> <table name="book"> <field name="id" type="int" primary-key="true" /> <field name="title" type="text" /> <field name="publisher_id" type="int" /> Hack #41: SQL-Anweisungen für Datenbanken automatisch erzeugen | 181 #41 HACK #41 SQL-Anweisungen für Datenbanken automatisch erzeugen Beispiel 5-25: XML-Beschreibung einer Datenbank (Fortsetzung) <field name="author_id" type="int" /> </table> <table name="publisher"> <field name="id" type="int" primary-key="true" /> <field name="name" type="text" /> </table> <table name="author"> <field name="id" type="int" primary-key="true" /> <field name="name" type="text" /> </table> </schema> Den Code für den Generator (Beispiel 5-26) speichern Sie als gen.php. Beispiel 5-26: Ein Skript zum Erzeugen des PHP- und Datenbankcodes <?php $tables = array( ); function start_element( $parser, $name, $attribs ) { global $tables; if ( $name == "TABLE" ) { $table = array( ); $fields = array( ); $table['name'] = $attribs['NAME']; $table['fields'] = array( ); $tables []= $table; } if ( $name == "FIELD" ) { $field = array( ); $field['name'] = $attribs['NAME']; $field['type'] = $attribs['TYPE']; $field['pk'] = ( $attribs['PRIMARY-KEY'] == "true" ) ? 1 : 0; $tables[count($tables)-1]['fields'] []= $field; } } function end_element( $parser, $name ) { } $parser = xml_parser_create( ); xml_set_element_handler($parser, "start_element", "end_element" ); while( !feof( STDIN ) ) { $text = fgets( STDIN ); xml_parse( $parser, $text ); } xml_parser_free( $parser ); 182 | Kapitel 5: Datenbanken und XML HACK SQL-Anweisungen für Datenbanken automatisch erzeugen Beispiel 5-26: Ein Skript zum Erzeugen des PHP- und Datenbankcodes (Fortsetzung) ob_start( ); foreach( $tables as $table ) { $pk = null; ?> DROP TABLE IF EXISTS <?php echo( $table['name'] ) ?>; CREATE TABLE <?php echo( $table['name'] ) ?> ( <?php $first = 1; foreach( $table['fields'] as $field ) { ?> <?php echo( $first ? "" : "," ) ?> <?php echo( $field['name'] ) ?> <?php echo( $field['type'] ) ?> <?php if ( $field['pk'] ) { $pk = $field['name']; ?> NOT NULL AUTO_INCREMENT<?php } ?> <?php $first = 0; } ?> <?php if ( $pk ) { ?> ,primary key( <?php echo( $pk ) ?> ) <?php } ?> ); <?php } $sql = ob_get_clean( ); $fh = fopen( "db.sql", "w" ); fwrite( $fh, $sql ); fclose( $fh ); ?> Den Hack ausführen Verwenden Sie den PHP-Interpreter auf der Kommandozeile, um diesen Code auszuführen: php gen.php < schema.xml Hierdurch wird die Datei db.sql erzeugt, die Code wie den unten gezeigten enthält (natürlich werden sich Ihre Ergebnisse je nach Datenbank und Tabellen von diesen hier unterscheiden): DROP TABLE IF EXISTS book; CREATE TABLE book ( id int NOT NULL AUTO_INCREMENT ,title text ,publisher_id int ,author_id int ,primary key( id ) Hack #41: SQL-Anweisungen für Datenbanken automatisch erzeugen | 183 #41 HACK #41 SQL-Anweisungen für Datenbanken automatisch erzeugen ); DROP TABLE IF EXISTS publisher; CREATE TABLE publisher ( id int NOT NULL AUTO_INCREMENT ,name text ,primary key( id ) ); DROP TABLE IF EXISTS author; CREATE TABLE author ( id int NOT NULL AUTO_INCREMENT ,name text ,primary key( id ) ); Dieser SQL-Code erzeugt die Tabelle, auf die das in schema.xml beschriebene Datenbankschema passt. Der XML-Code enthält sämtliche Tabellen und deren Inhalten. Dieser Code kann verwendet werden, um sowohl SQLAnweisungen [Hack #42] als auch PHP-Code, der die SQL-Anweisungen verwendet [Hack #37], zu erzeugen. Auf diese Weise sind SQL und PHP immer miteinander synchronisiert. Versuchen Sie auf keinen Fall, die Datei db.sql manuell zu aktualisieren. Nehmen Sie die Änderungen prinzipiell in der XML-Datei vor und erzeugen Sie den neuen SQL-Code dann mit dem Generator. Siehe auch • »Code für Datenbankabfragen automatisch erzeugen« [Hack #42] • »Automatisches Erzeugen von CRUD-Datenbankcode« [Hack #37] 184 | Kapitel 5: Datenbanken und XML