php
Tokyo Tyrant PHP, ein Key Value Store
14. Sep
Tokyo Tyrant ist eine Key Value Datenbank.
Im Gegensatz zu den sonst bekannten und verwendeten Datenbanken werden hier tatsächlich nur Werte zu eindeutigen Schlüsseln gespeichert.
Zudem gibt es noch die Möglichkeit zu eindeutigen Schlüsseln Werte Paare zu speichern. (TokyoTyrantTable)
Mehr Details: http://www.igvita.com/2009/02/13/tokyo-cabinet-beyond-key-value-store/
Beispiele
Im Code sieht das so aus:
Key => Value speichern:
-
$tt = new TokyoTyrant("localhost");
-
$tt->put("eindeutigerSchluessel", "Wert den ich speichern will");
-
// im obigen Fall würde "Wert den ich speichern will" ausgegeben.
Verwenden von TokyoTyrantTable:
-
// Parameter sind host und port des tyrant servers
-
$tt = new TokyoTyrantTable("localhost", 1979);
-
$array['test1'] = 'value4';
-
$array['test2'] = 'value2';
-
$array['test4'] = 'value4';
-
// keinen key angeben um automatisch einen index erzeugen zu lassen:
-
$index = $tt->put(null, $array);
-
// verwendet man bei put einen index welcher schon besteht wird der vorhandene ueberschrieben
-
$index = $tt->put($index , $array);
Eine TokyoTyrantTable durchsuchen:
-
// ein Query Objekt holen
-
$query = $tt->getQuery();
-
/* Eine Suchkondition hinzufuegen,
-
finde alle Zeilen beidenen test1 = value4 ist
-
*/
-
$query->addCond("test1", TokyoTyrant::RDBQC_STROR, "value4");
Anstatt die PHP Extension zu verwenden kann auch komplett über REST auf die Datenbank zugegriffen werden:
curl -X PUT -d 'value' 'http://localhost:1978/key'
curl 'http://localhost:1978/key'
// gibt value zurück
Die Datenbank kann also aus jeder Sprache verwendet werden welche http versteht.
Weitere Dokumentationen finden sich unter: http://de2.php.net/tokyo_tyrant
Installation
Tokyo Cabinet Paket herunterladen, entpacken,
configure
make
make install
aufrufen.
Tokyo Tyrant Paket herunterladen, entpacken,
configure
make
make install
aufrufen.
Zusätzlich musste ich noch das paket libbz2-dev (aptitude install libbz2-dev) installieren.
TokoyTyrant im Tabellen Modus Starten:
ttserver -port 1978 /tmp/temp_table.tct
TokyoTyrant im Key Value Modus starten:
ttserver -port 1978
Die Pecl PHP Extension kann mit
pecl install tokyo_tyrant
installiert werden anschliessen muss nur noch die ausgegebene Zeile:
extension=tokyo_tyrant.so
zur php.ini hinzugefügt und der Apache neugestartet werden.
Distributed TokyoTyrant
LightCloud - http://opensource.plurk.com/LightCloud/
Quellen weitere Informationen
http://1978th.net/tokyotyrant/spex.html#installation
http://petewarden.typepad.com/searchbrowser/2009/03/why-i-abandoned-tokyo-tyrant.html
http://petewarden.typepad.com/searchbrowser/2009/03/an-example-of-tokyo-tyrant-in-php.html
http://de2.php.net/manual/en/book.tokyo-tyrant.php
http://pecl.php.net/package/tokyo_tyrant/
Dependency Injection in PHP (IoC Pattern)
10. Sep
Kurze Recherche zu Dependency Injection in PHP (Inversion of Control Pattern)
Erläuterungen zu DI und IoC http://martinfowler.com/articles/injection.html
Seit einiger Zeit ist das Thema DI in PHP recht aktuell mittlerweile gibt es einige selbständige Dependency Injection Container und einige DI Container welche aus einem Framework entstanden sind oder zu diesem gehören.
Folgende DI Lösungen in PHP habe ich auf die schnelle gefunden und kurz angesehen:
- Symfony Dependency Injection ( http://components.symfony-project.org/dependency-injection/ )
Die DI Lösung des Symfony Frameworks, sehr ausführliche Dokumentation, kann sehr einfach mit anderen Frameworks verwendet werden (für Zend Framework keine anpassungen nötig). Konfiguration über pures PHP, YAML oder XML möglich. - Yadif ( http://code.google.com/p/yadif/ )
Konfiguration der Container über PHP, ausser dem Usage Example keine weitere Dokumentation gefunden. - Pico Container
DI Container welcher in mehreren Programmiersprachen umgesetzt wurde (u.a. Java, Dotnet, PHP)
SVN momentan nicht erreichbar.
Dokumentation ist sehr umfangreich inklusive Erklärungen zu den verschiedenen DI Arten
Wirklich getestet habe ich nur den Symfony DI Container, um das mal ein bisschen zu verdeutlichen hier eine Beispiel Konfiguration und ein bisschen Beispiel Code:
Als Konfigurationsformat habe ich XML ausgewählt die Konfiguration meines DI Containers für ein Beispiel Projekt sieht bei mir so aus
-
<?xml version="1.0" encoding="UTF-8"?>
-
-
<container xmlns="http://symfony-project.org/2.0/container">
-
<services>
-
-
<!-- PageCache -->
-
<service id="pagecache" class="Zend_Cache" shared="true" constructor="factory">
-
<file>Zend/Cache.php</file>
-
<argument>Page</argument>
-
<argument>File</argument>
-
<argument type="collection">
-
<argument key="lifetime">3600</argument>
-
<argument key="default_options" type="collection">
-
<argument key="make_id_with_get_variables">true</argument>
-
<argument key="make_id_with_cookie_variables">false</argument>
-
<argument key="specific_lifetime">3600</argument>
-
<argument key="cache_with_session_variables">true</argument>
-
<argument key="cache_with_post_variables">true</argument>
-
<argument key="cache_with_get_variables">true</argument>
-
<argument key="tags" type="collection">
-
<argument>page</argument>
-
</argument>
-
</argument>
-
<argument key="lifedebug_header">false</argument>
-
</argument>
-
<argument type="collection">
-
<argument key="cache_dir">../tmp/</argument>
-
</argument>
-
<call method="start">
-
</call>
-
</service>
-
<!-- ENDE PageCache -->
-
-
-
<!-- Loggging -->
-
<service id="log" class="Logger" shared="true">
-
<argument type="service">
-
<service class="Zend_Log" shared="true">
-
<argument type="service">
-
<service class="Zend_Log_Writer_Stream" shared="true">
-
<argument>../log/debug.log</argument>
-
<call method="setFormatter">
-
<argument type="service">
-
<service class="Zend_Log_Formatter_Simple" shared="true">
-
<argument>%%timestamp%%|%%sessionId%%|%%priorityName%%|%%fkn%%.%%line%%|%%message%%
-
</argument>
-
</service>
-
</argument>
-
</call>
-
</service>
-
</argument>
-
</service>
-
</argument>
-
<call method="setLevel">
-
<argument>7</argument>
-
</call>
-
</service>
-
<!-- ENDE Loggging -->
-
-
<!-- Cache -->
-
<service id="cache" class="Zend_Cache" shared="true" constructor="factory">
-
<file>Zend/Cache.php</file>
-
<argument>Core</argument>
-
<argument>File</argument>
-
<argument type="collection">
-
<argument key="automatic_serialization">true</argument>
-
</argument>
-
<argument type="collection">
-
<argument key="cache_dir">../tmp/</argument>
-
</argument>
-
</service>
-
-
<!-- END Cache -->
-
-
</services>
-
</container>
Die Konfiguration bewirkt das ich in der Anwendung nachher einen PageCache, einen Logger und einen normalen Cache einsatzbereit zur Verfügung habe sobald ich diese benötig.
Ein Hinweis noch zu den möglichen Attributen der Service Node besonders praktisch sind hier die Attribute "shared" und "constructor" mit dem shared Attribut kann angegeben werden ob nur eine Instanz dieses Service erstellt wird und bei jedem Zugriff darauf die selbe Instanz zurück gegeben wird, oder ob immer eine neue Instanz zurück gegeben wird. Über die "constructor" Attribut kann angebeben werden ob es sich um einen statischen oder nicht statischen Aufruf handelt. Für Zend_Cache wird der Aufruf Zend_Cache::factory(Core, File,...) verwendet. An der Klasse Logger wird der Konstruktor mit den angegebenen Parametern aufgerufen.
Im PageCache Beispiel wird direkt nach der Erstellung des Objekts noch die Methode start() aufgerufen.
Innerhalb der Anwendung wird der Container folgendermaßen initialisiert und Verwendet:
-
require_once $basePath.'/lib/sf/sfServiceContainerAutoloader.php';
-
-
// Symfony Autoloader registrieren
-
sfServiceContainerAutoloader::register();
-
-
// haben wir schon einen Fertigen DI Container?
-
{
-
require_once $configPath.'/di.container.conf.xml.php';
-
$sc = new SampleServiceContainer();
-
}
-
else
-
{
-
// noch kein DI Container vorhanden, also aus XML erstellen
-
$sc = new sfServiceContainerBuilder();
-
$loader = new sfServiceContainerLoaderFileXml($sc);
-
$loader->load($configPath.'/di.container.conf.xml');
-
$dumper = new sfServiceContainerDumperPhp($sc);
-
}
-
-
// Folgende Aufrufe können dann innerhalb der Anwendung verwendet werden
-
// Zugriff auf den Cache
-
$cache = $sc->cache;
-
-
// Zugriff auf den Logger
-
$log = $sc->log
noch Fragen? Doku anschauen ;-)
Zend_Log mit mongoDB
28. Aug
mal ein Kurzer Beitrag zu mongoDB.
Hab natürlich nur den PHP Treiber ausprobiert, Java wird aber wohl ähnlich wenn nicht gleich einfach zu bedienen sein.
Bin durch diesen Artikel draufgestoßen http://blog.mongodb.org/post/172254834/mongodb-is-fantastic-for-logging und hab es mal bei einem Projekt testweise eingebunden.
Zeigt zumindest mal einen Teil der Dinge in denen mongoDB gut ist:
- Asynchrone Inserts, daher kein warten auf ein File
- es gibt sogenannte Capped Collections, bei denen fliegen einfach die ältesten Daten aus der Collection raus (Konfigurierbar nach Anzahl der Objekte und Größe der Collection) quasi eine automatische rotation
- schnell
Um mongoDB zum Logging zu verwenden, hab ich lediglich einen neuen Zend_Log_Writer erstellt welcher die Logging Daten in eine mongoDB schreibt. Und diesen dem Logger zur Verwendung gegeben.
Dafür musste ich ungefähr 4 Zeilen Code selber schreiben:
...
$mongo = new Mongo();
$this->_db = $db->selectDB( "logs" )->createCollection(date('Y-m-d').'logs', true, 100000, 1000);
$this->_db->insert($dataToInsert);
...
der Rest der Arbeit bestand draus mir den Zend_Log_Writer_Db zu kopieren und die obigen Zeilen dort einzubauen.
Ok also was hat es gebracht? Gebracht hat es das ich jetzt die Anwendung mit fast vollem Log Level fahren kann und sich an der Geschwindigkeit zumindest spürbar nichts ändert.
Weitere Idee wäre zb, das man einen zentralen Logging Server hat und von anderen Anwendungen einfach dort hin schreiben kann.
mongoDB bietet auch so abgefahrene Sachen wie Replizierung und Fail-Over Lösungen.
Durchaus interessant wenn mal eine Datenbank gesucht wird in welche man einfach Objekte reinhauen kann.
Achso und den Server selbst aufsetzen war im Endeffekt nur mongoDb Archiv entpacken und mongod run aufrufen.
Links:
PHP Ubiquity Kommandos geupdatet
26. Jul
So ich hab es eben endlich geschafft mal die vor einiger Zeit erstellten php Kommandos für Ubiquity an die neue Version 0.5 anzupassen.
Die Kommandos sind immer noch unter den folgenden Urls erreichbar und können von dort bei installiertem Ubiquity abonniert werden.
Kommando php durchsucht die PHP Quickreference
und Kommando phpd durchsucht das PHP Manual.
Viel Spass damit.
SymfonyDay in Köln
16. Jul
Am 04.09.2009 gibt es den ersten SymfonyDay in Deutschland (genauer gesagt in Köln).
Die Registrierung ist bereits offen und der Schedule steht auch schon.
Geboten werden Talks und Workshops.
Das ganze ist mit 80€ incl Drinks und Essen auch ziemlich günstig.
Gesponsert wird der SymfonyDay09 von der in Köln ansässigen Interlutions GmbH welche auch gleich noch alle Teilnehmer zu Ihrer 10 Jahres Feier am Anschluss zum Symfony Day einlädt.
Also anmelden und in Köln einen bestimmt interessanten Tag erleben.
mozilla ubiquity kommandozeile für firefox
28. Aug
Interessante und praktische Kommandozeile für Firefox:
https://wiki.mozilla.org/Labs/Ubiquity/Ubiquity_0.1_User_Tutorial
installieren kann man es hier: https://people.mozilla.com/~avarma/ubiquity-0.1.xpi
hat man ubiquity installiert kann man mit "strg + leertaste" die Kommandozeile aufrufen.
mit command-list bekommt man eine Liste der verfügbaren Befehle.
Lässt sicht ziemlich leicht durch eigene Befehle erweitern hier einmal 2 schnell geschriebene Befehle um die php funktions Doku und die normale PHP Dokumenation zu durchsuchen:
PHP Funktionen durchsuchen:
http://taukon.de/ubiquity-php-function.php
PHP Dokumentation durchsuchen:
http://taukon.de/ubiquity-php-function-doc.php
Base64 decodieren encodieren:
http://taukon.de/ubiquity-base64.php
Symfony Admin Generator auf Deutsch
14. Nov
Grade gefunden, D-Down bietet auf seiner Seite die Übersetungen für den Admin Generator von Symfony an. http://coding.d-down.de/blog/archives/47-Die-deutsche-UEbersetzung-der-Admin-Generator-Begriffe-von-Symfony.html
Hab die obere Datei nocheinmal erweitert und auch bereits in das richtige XLIFF Format gebracht. Runterladen _hier_ .
Da ich auch erst mal rumsuchen musste wie man es verwendet hier noch einmal alle Schritte.
- in der apps/backend/config/settings.yml den auskommentierten i18n Eintrag unter .settings auf "on" stellen.
- obige Datei unter apps/backend/i18n/messages.de_DE.xml speichern. dabei Format so anpassen wie es unter ( http://www.symfony-project.com/book/1_0/13-I18n-and-L10n#Using Dictionary%20Files ) in figure 13-14 steht... <xml><body... am anfang und ende ergänzen. (bei meiner Datei schon geschehen)
- unter backend/config/i18n.yml:
all:
default_culture: de_DE
source: XLIFF
debug: off
untranslated_prefix: "[t]"
untranslated_suffix: "[/t]"
eintragen.
- symfony cc
- browser neu starten oder cookies löschen
Wird der Admin Generator erneut aufgerufen sollten die meisten Texte eingedeutscht sein. Stellt man in der i18n.yml das debugging auf on, kann man auch sehr schnell erkennen welche nicht übersetzt wurden und diese gegebenenfalls in der eigenen messages.de_DE.xml nachpflegen.