Muss man denn hier alles selber machen?

Natürlich nicht! Wir arbeiten mit Maschinen, deren Zweck es, ist uns Arbeit abzunehmen. Eine dieser Arbeiten ist das Erstellen von Testobjekten für die Entwicklung einer Applikation. Zum einen muss man feststellen, ob die Programmlogik auch das tut, was man selbst oder der Kunde von ihr erwartet. Zum anderen braucht man die Testobjekte natürlich auch für das Design. Wer traut sich schon zu das Aussehen eines Blogs ansprechend zu gestalten, ohne vorher mal ausreichend Testcontent zu pflegen?

Manche sagen, dass solche Arbeiten etwas für Praktikanten sind. Ich sage, dass so einen Job ein Computer am besten selbst erledigt. Dazu hat das SilverStripe Framework Sapphire auch schon eine Methode parat: requireDefaultRecords(). Sie wird in den Kindern der Klasse DataObject jedes mal aufgerufen, wenn die Datenbank mit einem dev/build erneuert wird. Das Blogmodul benutzt requireDefaultRecords() beispielsweise um bei der Installation gleich einen BlogHolder und einen BlogEntry zu instanziieren.

Wo bleiben denn die Heinzelmännchen?

Bei der Entwicklung meines Ticketsystems brauche ich natürlich ausreichend Testobjekte, um mir das Handling im Backend und das Aussehen im Frontend vorstellen zu können. Dummerweise muss ich an den Objekten immer mal wieder was verändern: Neue Beziehungen, alte Beziehungen löschen, Änderungen bei den Attributen, und so weiter. Weil nach diesen Änderungen die bestehenden Objekte in der Datenbank Probleme verursachen, muss ich sie löschen und neue Objekte anlegen. Das kostet mich jedes mal Zeit und Motivation. Deshalb hab ich mir eine kleine Methode geschrieben, die mir da hilft:

/**
 * Erzeugt und befüllt Testobjekte
 * @param string $className Name der zu instanziierenden Klasse
 * @param string $emailAddress als Wert für ein Objektattribut
 * @param string $loremIpsum Testfließtext
 * @param int $objectAmount Anzahl der zu erzeugenden Instanzen
 */

function createObjects($className,
              $emailAddress = 'meineEmailAdresse',
              $loremIpsum = 'Lorem ipsum dolor amit...', $objectAmount = 5) {
      if (!DataObject::get($className)) {
              for ($i = 1; $i <= $objectAmount; $i++) {
                      $obj = new $className();
                      $attributes = $obj->inheritedDatabaseFields();
                      foreach ($attributes as $key => $value) {
                              if ($key == "Title" or $key == "title" or $key == "Name" or $key == "name") {
                                      $obj->{$key} = $className . $i;
                              } elseif ($key == "email" or $key == "Email" or $key == "EMail") {
                                      $obj->{$key} = $emailAddress;
                              } elseif ($key == "Message" or $key == "message" or $key == "body" or $key == "Body") {
                                      $obj->{$key} = $loremIpsum;
                              } elseif ($key == "Author" or $key == "author" or $key == "autor" or $key == "Autor") {
                                      $obj->{$key} = "Tester$i";
                              }
                      }
                      $obj->write();
              }
      }
}
  • Der Algorhythmus wird nur ausgeführt, wenn noch keine Objekte der Klasse vorhanden sind.
  • Mit einer for - Schleife wird der Algorhythmus jetzt so oft ausgeführt, wie in $objectAmount definiert.
  • Mit der Methode inheritedDatabaseFields() werden die Attribute der Klasse und ihrer Elternklassen in ein assoziatives Array gespeichert.
  • Jetzt wird auf typische Attribute geprüft, um diese mit dem passenden Content zu befüllen.

Jetzt muss die Methode natürlich auch noch aufgerufen werden:

function requireDefaultRecords() {
              parent::requireDefaultRecords();
              $this->createObjects('SomeObject', 'test@test.de');
              $this->createObjects('OtherObject', 'test@test.de', NULL, 20);
      }

Geht ´s nicht auch einfacher?

Das ganze ist natürlich beliebig erweiterbar. Man könnte auch für jede Klasse den passenden Algorhythmus schreiben, der genau ihre Attribute befüllt. Das ist etwas mehr Arbeit, dürfte aber hin und wieder unausweichlich sein. Man kann zwar die Attribute dynamisch ansprechen, der für sie passende Content lässt sich aber nicht immer durch ein Programm bestimmen.

function requireDefaultRecords() {
              parent::requireDefaultRecords();
              $className = 'MyDataObject';
              $objectAmount = 20;
              if (!DataObject::get($className)) {
                      for ($i = 1; $i <= $objectAmount; $i++) {
                              $obj = new $className();
                              $obj->Title = $className . $i;
                              $obj->Email = 'test@test.de';
                              $obj->Value = '12345';
                              $obj->write();
                      }
              }
      }

Die Werte der Attribute lassen sich durch die Verwendung des Index $i noch leicht dynamisieren.

Tags: