< Voriger Tag
Freitag, 22. Januar 2010
Für das Dr. Web Magazin habe ich ein Tutorial mit einen verspielten Follow Mouse-Effekt geschrieben. Zitat:
Die Mausspur ist ein reichlich verspielter Effekt, den es auch schon zu DHTML-Zeiten gegeben hat. Der Mauszeiger wird von einzelnen Bildern oder Buchstaben verfolgt. Der auffällige Effekt kann für sich selbst stehen oder eine kurze Botschaft transportieren. Das Tutorial erklärt ausführlich das nötige Scripting.
Das Tutorial inklusive Kommentare: JavaScript Tutorial: Eine effektvolle Mausspur mit Follow Mouse
[Direktlink]
Freitag, 01. Januar 2010
Die Task-Klasse ist nun mit RuBisCo ORM generiert. Neu hinzugekommen ist das Erstellungsdatum einer Aufgabe.
Zur Vorbereitung sind gestern PHPUnit-Tests für Todo hinzugekommen, so dass automatisch getestet werden kann, ob die generierte
Task-Klasse auch das macht, was die bisherige Klasse tat und die "Dokumentationskommentare" im ClassDB-Template sind in die Dokumentation gewandert, so dass sie nicht im generierten Code stören.
public function read($id = null) {
if(null === $id) {
$id = $this->_id;
}
//$sqlReadTask = 'SELECT id, task, status FROM tasks WHERE id = :id';
$sqlReadTask = 'SELECT {fieldNames} FROM {tableName} WHERE id = :id';
Task ersetzen
Das Ersetzen der Task-Klasse durch die generierten Task- und TaskDB-Klassen heute funktionierte dann gut. Zwei statt der vorigen einen Task-Klasse damit das System flexibler ist. Task ist das Modell mit den Eigenschaften und Set-/Get-Methoden und TaskDB die Erweiterung für die Datenbanknutzung. Statt Datenbank könnte dann auch eine REST-API oder das Dateisystem benutzt werden.
created
Nachdem das lief ist dann die Erweiterung um das Erstellungsdatum einer Aufgabe hinzugekommen. DateTime-Typ hinzugefügt, Tabellenbeschreibung erweitert, Task-Klasse generiert, TasksView und TaskView von Hand um created erweitert und noch an paar Änderungen an der index.php -- funktioniert mit dem ORM soweit ganz gut.
Bei den ganzen Punkten gab es zusammengenommen dann noch eine Reihe an kleineren Bugfixes und Änderungen an den ORM- und Todo-Dateien.
Quelltext (MIT Lizenz)
Die kompletten Quelltexte liegen in Subversion:
Todo: heutige Revision 25, aktuelle Version -- ORM: heutige Revision 25, aktuelle Version
[Direktlink]
Samstag, 26. Dezember 2009
Neu hinzugekommen die Application-Klasse für Applikationsname, Namensraum und später auch Autoren, Copyright, ... und die Template-Klasse für das Ersetzen der Platzhalter inklusive Einrückung.
Application
Application speichert direkt die Namen für die Applikation, den Namensraum, den Metadaten und besitzt ein Array für die Tabellen. In Table werden diese Daten in die Vorlagen eingesetzt.
class Application {
public $name;
public $namespace;
public $authors;
public $copyright;
public $license;
public $tables = array();
Template
Template ist in dieser ersten Version eine sehr einfache, zusammengehackte Klasse zum Ersetzen der Platzhalter in den Vorlagen. Hauptsächlich entstanden, um die Platzhalter sinnvoll einzurücken.
Das sieht innerhalb von replace() unübersichtlich aus. Im Wesentlichen wird dort folgendes gemacht:
- Suche nach eingerückten Zeilen mit Platzhalter
- Extrahiere die Einrückung
- Wandel den einzusetzenden Inhalt in die Zeilen eines Arrays um
- Füge diese Zeilen inklusive Einrückung in die Vorlage ein
public function replace($name, $content) {
// Replace with indent
$newTemplate = '';
foreach(\split("\n", \rtrim($this->template)) as $line) {
// {fieldDeclaration}
if(\preg_match("#^(\s*)\{$name\}\s*$#", $line, $matches)) {
$indent = $matches[1];
// Convert $content to array
$a = null;
if(\is_array($content)) {$a = $content;}
if(\is_string($content)){$a = \split("\n", rtrim($content));}
if(is_null($a)) {
$a = array($content);
echo "Warning: Not supported type\n"; // TODO
}
// Replace placeholder with content
foreach($a as $item) {
$newTemplate .= "{$indent}{$item}\n";
}
} else {
$newTemplate .= $line . "\n";
}// if(\preg_match("#^(\s*)\{$name\}\s*$#", $line, $matches)) {
}// foreach(\split("\n", $this->template) as $line) {
$this->template = $newTemplate;
// Replace without indent
$this->template = \str_replace('{' . $name . '}', $content, $this->template);
}// replace
Quelltext (MIT Lizenz)
Der komplette Quelltext von RuBisCO ORM liegt in Subversion:
Heutige Revision 11, aktuelle Version.
[Direktlink]
Donnerstag, 24. Dezember 2009
friede
auf erden
[Direktlink]
Mittwoch, 23. Dezember 2009
Das Grundprinzip mit einzelnen Klassen für die Datentypen plus Methoden zur Quelltextgenerierung funktioniert. Im Prototyp sind Int und VarChar implementiert.
#!/usr/local/php
<?php
namespace rubisco\tools\orm;
ini_set('include_path', '../:' . ini_get('include_path'));
require_once 'Table.php';
require_once 'Type/Int.php';
require_once 'Type/VarChar.php';
$table = new Table('testOnlyID');
$table->fields[] = new Type\Int('id', 1); // name, min, max
$table->fields[] = new Type\VarChar('status', 20, true); // name, length, notEmpty
echo $table->generateCode();
?>
Macht daraus für die setStatus()-Methode:
public function setStatus($value) {
if(('' !== $value) && (strlen($value) <= 20)) {
$this->_status = $value;
return $this;
} else {
throw new \Exception(__CLASS__ . " Wrong value for status attribute.");
}
// setStatus
Von der Programmierung ist das nicht besonders spannend. Die Vorlagen der Klassen liegen in templates und die dortigen Platzhalter werden mit str_replace() ersetzt. Die generateMethod()-Methode zur Generierung der obigen setStatus() ist folgende:
public function generateMethod() {
$ucName = ucfirst($this->name);
$conds = array();
if($this->notEmpty) {
$conds[] = "('' !== \$value)";
}
$conds[] = "(strlen(\$value) <= {$this->length})";
$conds = join(' && ', $conds);
$code = <<< EOD
public function set{$ucName}(\$value) {
if($conds) {
\$this->_{$this->name} = \$value;
return \$this;
} else {
throw new \Exception(__CLASS__ . " Wrong value for {$this->name} attribute.");
}
}// set{$ucName}
EOD;
return $code;
}// generateMethod
Mehr Informationen nötig
Statt nur CREATE TABLE ... werden dann noch zusätzlich der Applikationsname, der Namensraum und Metadaten wie Copyright, Lizenz, ... benötigt. Spezifische Fehlermeldungen für die einzelnen Überprüfungen müßte es auch noch geben.
Quelltext (MIT Lizenz)
Der komplette Quelltext von RuBisCO ORM liegt in Subversion.
[Direktlink]
Dienstag, 22. Dezember 2009
Die erste Version von RuBisCO Todo habe ich in ca. 8 Stunden geschrieben. RuBisCO ORM soll das Grundgerüst eines solchen Webprogramms per Mausklick aus einer SQL-Tabellendefinition plus zusätzlicher Informationen zur Überprüfung der Eingabe generieren.
Im Fall von RuBisCO Todo also aus:
CREATE TABLE tasks (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
task VARCHAR(256) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT "open"
) ENGINE = innodb
DEFAULT CHARSET = utf8;
Plus den zusätzlichen Informationen zur Überprüfung der Eingabe:
CREATE TABLE tasks (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
task VARCHAR(256) NOT NULL rbsNotEmpty,
status VARCHAR(20) NOT NULL DEFAULT "open"
rbsOptions = ["open", "closed", "work", "finished"]
) ENGINE = innodb
DEFAULT CHARSET = utf8;
Dabei wird der ORM auch Joins und Foreign Keys unterstützen, so dass das status-Feld zur Normalisierung in eine eigene Tabelle ausgelagert werden kann:
CREATE TABLE tasks (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
task VARCHAR(256) NOT NULL,
status INT NOT NULL DEFAULT 1,
FOREIGN KEY (status) REFERENCES status(id)
)
ENGINE = innodb,
DEFAULT CHARSET = utf8;
CREATE TABLE status (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
status VARCHAR(20) NOT NULL DEFAULT "open"
rbsOptions = ["open", "closed", "work", "finished"]
)
ENGINE = innodb
DEFAULT CHARSET = utf8;
Aufgebaut ist RuBisCO ORM aus Klassen für die SQL-Tabellen und -Felder, deren Methoden den Quelltext generieren:
namespace rubisco\tools\orm;
class SQLTable {
public $name;
public $fields = array();
}// SQLTable
namespace rubisco\tools\orm\type;
class SQLField {
public $name;
public $default;
public $notNull;
public $foreignKey;
public $preg; // String
public $pregMatch; // Bool
}// SQLField
namespace rubisco\tools\orm\type;
class SQLInt extends SQLField {
public $min;
public $max;
}// SQLInt
Hmm, mal anhand eines Prototyps für eine Tabelle nur mit id INT ausprobieren, ob es grundsätzlich wie gedacht funktioniert.
[Direktlink]
Montag, 21. Dezember 2009
RuBisCO Todo ist ein einfaches Webprogramm für To-do-Listen -- es dient zur Planung für den Aufbau der RuBisCO-Site.
Task
Zentrale Klasse ist Task. Sie dient als Active Record zum Speichern und Lesen der Daten und überprüft zugleich, ob die eingegebenen Daten dem gewünschten Muster entsprechen.
class Task {
private $todo;
private $dbh;
private $getFilter = 'RAW';
private $_id = null;
private $_task = null;
private $_status = null;
public function read($id = null) ...
public function insert() ...
public function update() ...
public function delete() ...
...
}// Task
Überschreiben von __set()
Dazu wird die __set()-Methode überschrieben. Diese wird von PHP aufgerufen wenn mit $task->id = 42 eine Zuweisung erfolgt und die Eigenschaft, in diesem Fall 'id', nicht im Objekt existiert oder nicht für den Aufrufer sichtbar ist, z.B. weil sie als private deklariert ist und die Zuweisung wie hier von außen und nicht innerhalb des Objekts mit $this->id = 42 erfolgt. Damit __set() auch innerhalb aufgerufen wird ist in Task den Eigenschaften (id, task, status) ein _ vorangestellt: $_id, $_task, $_status.
Überschrieben ist __set() so, dass eine zur jeweiligen Eigenschaft dazugehörige Methode aufgerufen wird id -> setId(), task -> setTask(), ... bzw. eine Exception geworfen wird, wenn die Eigenschaft nicht existiert.
public function __set($name, $value) {
$methodeName = 'set' . ucfirst($name);
if(method_exists($this, $methodeName)) {
$this->$methodeName($value);
} else {
throw new Exception(__CLASS__ ." No '{$name}' attribute");
}
}// __set
Überprüfung in setXXX()
In den setXXX()-Methoden wird dann überprüft, ob die Eingabe dem gewünschten Muster entspricht.
public function setId($value) {
if(preg_match('/^\d+$/', $value)) {
$this->_id = $value;
return $this;
} else {
throw new Exception(__CLASS__ . " Wrong value for id attribute.");
}
}// setId
Quelltext (MIT Lizenz)
Der komplette Quelltext von RuBisCO Todo liegt in Subversion.
[Direktlink]
< Voriger Tag
|