Portal > Foren > PHP > PEAR, PECL und Frameworks > Erfahrungsaustausch und Best Practices: Doctrine ORM
Antwort
 
LinkBack Themen-Optionen Thema durchsuchen
Alt 26.08.2009, 11:14 Nach oben    #1
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Koblenz
Beiträge: 4.794
Standard Erfahrungsaustausch und Best Practices: Doctrine ORM

Hallo,
ich werde mich in Kürze mal etwas intensiver mit Doctrine beschäftigen und wollte an dieser Stelle im Voraus mal ein paar Erfahrungsberichte sammeln.

Ich steh eigentlich nicht so auf ORM, aber ich will mich da auch nicht verschließen und sich weiterzubilden schadet bekanntlich auch nicht.

Wer also schon mal mit Doctrine gearbeitet hat und Lust hat seine Erfahrungen (Performance, Usability, Wartbarkeit, Spaß an der Freunde, ..) mit mir zu teilen, der darf sich gerne an diesem Thread beteiligen.

Ich werf da mal einen Blick auf den robo, der ja laut eigenen Angaben Doctrine nutzt.

Danke im Voraus.


EDIT.
Vielleicht kann der Titel noch in "Erfahrungsaustausch und Best Practices: Doctrine ORM" geändert werden oder so.
Denn natürlich bin ich auch an Best Practices interessiert. Logisch!
__________________
Mehr TuS Koblenz geht nicht ... - TuS Koblenz Forum ... Benjamin Klaile ist noch in der Aufwärmphase

Geändert von Ben (26.08.2009 um 11:21 Uhr)
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 26.08.2009, 13:19 Nach oben    #2
Benjamin Steininger
 
Benutzerbild von robo47
 
Registriert seit: 02.06.2005
Ort: weiher im tiefsten Odenwald
Beiträge: 1.379
Standard

Also ich habe, weil ich mich mal mit nem ORM-System auseinandersetzen wollte bei meinem Blog Doctrine eingesetzt.
Zur Auswahl standen damals Propel und Doctrine und ich hab mich dann für Doctrine entschieden, weil mir die Doku auf den ersten Blick mehr zugesagt hat, bei einem anderen Projekt werde ich mir jetzt Propel mal etwas genauer anschauen.

Alles in allem muss man sich darüber klar sein dass so ein System wie Doctrine schon eine Menge overhead (vor allem auch Speicherverbrauch) mit sich bringt.

Wen man schon mit Frameworks ala Zend Framework gearbeitet hat ist man das ja schon etwas gewöhnt, auch eine hohe Anzahl an Dateien/Klassen die auf JEDER Seite oftmals gebraucht werden. Bei mir sind das für den Core von Doctrine zwischen 40 und 70 Dateien/Klassen + die genutzen Klassen für die Datenbankabstration (2 pro Tabelle [Base + normal]) die auf der Seite gebraucht werden.
Ich komme auf manchen Seiten mit Zend Framework, HtmlPurifier, ezCompontents und Doctrine auf bis zu 350 geladene Dateien (inklusive Views, PHP-Konfigurations-Dateien etc [Sowas ist aber performant wohl auch nur mit APC oder einem anderen Bytecode-Cache realisierbar]) und auch auf einen Speicherverbrauch zwischen 3mb und 12mb pro Seite, im Schnitt dürften es so ~ 5mb sein die da zusammenkommen, auch abhängig davon ob caching aktiviert ist oder nicht.
Im Vergleich zu meinem vorherigen Blog-System (frickel eigen-bau mvc-System mit smarty) das im Schnitt mit < 15 Dateien auskam und < 3mb speicher / seite brauchte war das halt schon ein ein riesen Unterschied.

Der Komfort dass man halt aus der Konfigurations-Datei sich direkt seine fertigen Klassen (inklusive der Beziehungen) generieren, die Tabellen in der Datenbank und soweiter generieren kann ist halt grandios, man muss eigentlich kaum noch joins verwenden, weil die ganzen vorher definierten Beziehungen von Doctrine erkannt werden und die Querys automatisch generiert + Verknüpft werden und man am Ende eine schöne Objekt-Struktur inklusive der Relationen zurückbekommt.

Wichtig ist vor allem bei so einem System dass man immer mal nen Blick auf den Profiler von Doctrine wirft um zu schauen was wirklich an Querys gemacht wird.
Es lädt ein zur Faulheit um mal ein Beispiel zu nennen:

Ich hab für den Blog 3 Tabellen: Blogentry, Tag, Comment

Die sind natürlich verknüpft (dabei entstehen 2 weitere Tabellen), wenn ich mir also 10 Blogentrys abhole kann ich via
PHP-Code:
$blogentries Doctrine::getTable('Blogentry')->createQuery()->select()->limit(10)->orderBy('id')->execute();
foreach(
$blogentries->Tag as $tag) {

(Tag ist dabei der in der Konfig angegebene Name der Beziehung zwishcen Blogentry und Tag)
direkt auf die Tags des Eintrags zugreifen, gleiches gilt für die Kommentare. Das ganze passiert aber wenn man sich nur die Blogeinträge aus der Datenbank bezogen hat via lazy-load was bei einem solchen beispiel:

PHP-Code:
$blogentries Doctrine::getTable('Blogentry')->createQuery()->select()->limit(10)->orderBy('id')->execute();
foreach (
$blogentries as $entry) {
echo 
$entry->name ' Kommentare: ' count($entry->Comment) . '<br />';
echo 
'Tags: ' 
foreach(
$entry->Tag as $tag) {
echo 
$tag->name;
}

halt bedeutet dass 21 Querys ausgeführt werden.
1 für die 10 Blogeinträge
Und in jedem schleifendurchlauf eins für die Tags und eins für die Kommentare (Wobei man hier z.b. ja eigentlich nur die Anzahl will, werden sie trotzdem alle abgerufen und Objekte davon erstellt).

Wenn man sowas nicht direkt weis, bzw. sich nicht ausreichend mit dem System befasst hat, ist das zwar auf den ersten Blick super komfortabel, aber die Performance ist halt unter aller Sau.

Dazu gibt es aber auch Beiträge im Manual wo man dann zu querys dieser Art kommt, wo aus den 21 dann wieder ein Query wird:

PHP-Code:
        $entries Doctrine_Query::create()
                    ->
from('Blogentry b')
                    ->
leftJoin('b.Tag t')   // Left Join auf die Beziehung Tag
                    
->leftJoin('b.Comment c''ON c.checked = 1'// Left Join auf die Beziehung Comment + nur freigeschaltene Kommentare             
                    
->orderBy('b.created_at DESC, b.id DESC'// sortiert nach Datum und id
                    
->execute(); 
das generierte SQL dazu sähe dann so aus:
Code:
SELECT
    b.id AS b__id,
    b.name AS b__name,
    b.description AS b__description,
    b.message AS b__message,
    b.created_at AS b__created_at,
    b.updated_at AS b__updated_at,
    t.id AS t__id,
    t.tag AS t__tag,
    t.name AS t__name,
    c.id AS c__id,
    c.user AS c__user,
    c.description AS c__description,
    c.email AS c__email,
    c.homepage AS c__homepage,
    c.comment AS c__comment,
    c.checked AS c__checked,
    c.created_at AS c__created_at,
    c.updated_at AS c__updated_at
FROM 
    blogentry b 
        LEFT JOIN 
            blogentry2_tag b2 
                ON (b.id = b2.blogentry_id) 
        LEFT JOIN 
            tag t 
                ON t.id = b2.tag_id 
        LEFT JOIN 
            blogentry2_comment b3 
                ON (b.id = b3.blogentry_id) 
        LEFT JOIN 
            comment c 
                ON c.id = b3.comment_id 
ORDER BY
    b.created_at DESC,
    b.id DESC

Auch wenn man z.b. mit einem Cache alla Zend_Cache arbeitet und die Objekte serialisiert muss man vorsichtig sein, z.b. werden die genannten Relationen von Objekten (z.b. Tag und Comment bei Blogentry) selbst wenn sie schonmal abgerufen wurden und vorhanden sind, standardmäßig nicht mit-serialisiert, ausser man sagt es jedem Objekt, was bei mir dann darin resultierte, dass ich zwar nen Cache hatte, aber darin nur die 10 Blogeinträge waren und die Relationen wieder alle via Lazy-Load nachgeladen wurden und ich so 20 zusätzliche Querys bei der Ausgabe hatte. (Die Methode serializeReferences(true) der Doctrine_Records hilft da dann weiter)

Also Systeme wie Doctrine sind definitiv nichts was man mal eben so in 30 Minuten versteht und mit einbaut, sondern man muss bei sehr vielen Sachen auch genau schauen was im Hintergrund wirklich passiert, das Manual lesen und soweiter um nicht total unperformanten Code zu schreiben.

Dazu: http://www.doctrine-project.org/docu...ng-performance

Den Rest finde ich allerdings super, gerade auch z.b. die Vererbung oder auch Template ( http://www.doctrine-project.org/docu...1/en/behaviors ) die man für Tabellen verwenden kann.
z.b. kann man automatisch via den Templates einen Baum als NestedSet machen, oder mit Timestampable wird dem Objekt automatisch komplett transparent im Hintergrund automatisch ein Erstellungs und Update-Datum verpasst, das automatisch von Doctrine bei der Erstellung und jeder Änderung eines Datensatzes angepasst wird.

Desweiteren gibt es auch nette Gimmicks wie Validatoren, dass ein Eintrag nur vorgenommen wird wenn gewisse Spalten (Email-Feld oder ähnliches) gegen einen Regex validieren, sonst fliegt beim erstellen / updaten eine Exception etc.

Und durch seinen Aufbau ist es auch extrem erweiterbar, seien es eigene Validatoren, eine Eigene Basis-Klasse für die Records, eigene Behaviours oder sonstwas die man erstellen kann. Also definitiv ein mächtiges Werkzeug das einem einige Arbeit ersparen kann, viel komfort mit sich bringt, allerdings aus reiner Performance-Sicht sicherlich nicht ideal ist und oftmals auch einige Kniffe bedarf bis man seine Probleme performant gelöst hat.

Auch wenn ich schon ne Zeit lang mit Doctrine herumwerkel hab ich viele Bereich noch garnicht angekratzt die Doctrine auch kann, z.b. die Migrations oder ähnliches wo man an einem wachsenden System änderungen an der Datenbank-Struktur durchführen kann quasi ohne dass man etwas in der Applikation ändern muss und solche Sachen.

// Fast sämtlicher Code ist händisch geschrieben / ungetestet, also bitte nicht drauf festnageln :)
robo47 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 26.08.2009, 13:37 Nach oben    #3
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Koblenz
Beiträge: 4.794
Standard

Wow, danke sehr.
Ich weiß gerade gar nicht so genau, was ich davon halten soll. Auf der einen Seite steht
Zitat:
Ich komme auf manchen Seiten mit Zend Framework, HtmlPurifier, ezCompontents und Doctrine auf bis zu 350 geladene Dateien (inklusive Views, PHP-Konfigurations-Dateien etc [Sowas ist aber performant wohl auch nur mit APC oder einem anderen Bytecode-Cache realisierbar]) und auch auf einen Speicherverbrauch zwischen 3mb und 12mb pro Seite, im Schnitt dürften es so ~ 5mb sein die da zusammenkommen, auch abhängig davon ob caching aktiviert ist oder nicht.
was sich doch eher negativ anhört und auf der anderen Seite scheinst du aber durchaus zufrieden mit dem Einsatz von Doctrine zu sein.


Fest steht aber nach der Lektüre deines Textes auf jeden Fall das, was ich bereits vermutet (befürchtet will ich mal nicht sagen) habe: es ist viel Zeitaufwand nötig!

Ich muss allerdings nochmal nachhaken, was das "Profiling" angeht. Wie genau überprüfst du denn, ob du performant oder eben nicht arbeitest?
Klar, ich könnt mir da jetzt entsprechende Vergleichsskripte schreiben etc., aber das ist ja dann doch ein enormer Zusatzaufwand, der im Bezug auf das Ergebnis eventuell gerechtfertigt sein kann, aber ja nicht unbedingt sein muss. ;)
__________________
Mehr TuS Koblenz geht nicht ... - TuS Koblenz Forum ... Benjamin Klaile ist noch in der Aufwärmphase
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 26.08.2009, 14:31 Nach oben    #4
Benjamin Steininger
 
Benutzerbild von robo47
 
Registriert seit: 02.06.2005
Ort: weiher im tiefsten Odenwald
Beiträge: 1.379
Standard

Zitat:
Zitat von Ben Beitrag anzeigen
Wow, danke sehr.
Ich weiß gerade gar nicht so genau, was ich davon halten soll. Auf der einen Seite steht
Zitat:
Ich komme auf manchen Seiten mit Zend Framework, HtmlPurifier, ezCompontents und Doctrine auf bis zu 350 geladene Dateien (inklusive Views, PHP-Konfigurations-Dateien etc [Sowas ist aber performant wohl auch nur mit APC oder einem anderen Bytecode-Cache realisierbar]) und auch auf einen Speicherverbrauch zwischen 3mb und 12mb pro Seite, im Schnitt dürften es so ~ 5mb sein die da zusammenkommen, auch abhängig davon ob caching aktiviert ist oder nicht.
was sich doch eher negativ anhört und auf der anderen Seite scheinst du aber durchaus zufrieden mit dem Einsatz von Doctrine zu sein.
Man muss sich immer überlegen was im Vordergrund steht, was einem zur Verfügung steht, welchen Komfort und Luxus man haben will, welche Räder man nicht neu erfinden will und wie gut die eigenen Kenntnisse und Fähigkeiten im Bereich Software-Design sind.
Egal welches Framework, welche Bibliothek, welches ORM-System oder was auch immer man einsetzt, man wird immer overhead haben und gerade bei objekt-orientieren System die durchdacht sind und meistens noch sehr stark erweiterbar kommt hier halt immer einiges Zusammen.

Wenn Performance das A&O des Projektes ist, muss man sich halt überlegen ob es sich lohnt weniger Gebrauch von den ganzen Sachen zu machen, wenn man sich aber sagt bis ich eine perfekten Ersatz für zend framework, orm und co erfunden habe dauert das mit testen und co XXXX Stunden das kostet mich XXXX € ... dafür kann ich mir für das Projekt aber auch anstatt einem Server vielleicht 3 hinstellen und bin 1/2 Jahr früher fertig und setzte auf Best-Practices auf, auf Code der weiterentwickelt und getestet wird, an dem viele Leute mitarbeiten und wo ich auch später vielleicht Problemlos entwickler finde die sich schon damit auskennen die man nicht erst einlernen muss ... kann sich das auch bezahlt machen.

Systeme wie ZF, ezComponents, Symfony, Doctrine, Propel und Co bringen halt eben das mit, Best-Practices, hohe Erweiterbarkeit, Code-Qualität, etc, der Preis ist halt immer dass man etwas einsetzt was für die Allgemeinheit entwickelt wurde und nicht speziell für den eigenen Use-Case und dass diese Systeme eben auch gewisse Anforderungen stellen.

Oftmals ist es auch einfach nur "kleinkram" der halt jetzt bei der Anzahl der Dateien ziemlich reinhaut, htmlpurifier, den ich NUR nutze um das HTML der Kommentare ordentlich zu filtern ist schon ziemlich groß und mächtig und kann halt auch noch einiges mehr das ich nicht nutze, nichts desto trotz sind das 68 Dateien die er lädt, weil er eben alles in kleinste Komponenten zerlegt hat und so noch erweiterbar/flexibel ist.

Mal ein paar statistiken erstellt mit phploc zu systemen die ich einsetze um mal zu sehen wie viel Code, Klassen und Dateien hinter manchen Sachen steckt.

html purifier 4.0
Größe: 4,4 MB
Code:
phploc 1.1.1 by Sebastian Bergmann.

Directories:                               27
Files:                                    216

Lines of Code (LOC):                    22080
Comment Lines of Code (CLOC):            8592
Non-Comment Lines of Code (NCLOC):      13488

Interfaces:                                 0
Classes:                                  211
Non-Static Methods:                       597
Static Methods:                            38
Functions:                                 29
zend framework 1.9.0
Größe: 47 MB
Code:
phploc 1.1.1 by Sebastian Bergmann.

Directories:                              409
Files:                                   1901

Lines of Code (LOC):                   377754
Comment Lines of Code (CLOC):          176680
Non-Comment Lines of Code (NCLOC):     201074

Interfaces:                                94
Classes:                                 1805
Non-Static Methods:                     11369
Static Methods:                           805
Functions:                                436

doctrine 1.1.3
Größe: 5,9 MB
Code:
phploc 1.1.1 by Sebastian Bergmann.

Directories:                               69
Files:                                    343

Lines of Code (LOC):                    67045
Comment Lines of Code (CLOC):           30905
Non-Comment Lines of Code (NCLOC):      36140

Interfaces:                                10
Classes:                                  333
Non-Static Methods:                      2292
Static Methods:                           113
Functions:                                 19
ezComponents 2009.1 (davon nutze ich aktuell nur die Klasse für Graphen)
Größe: 33 MB
Code:
phploc 1.1.1 by Sebastian Bergmann.

Directories:                              360
Files:                                   1868

Lines of Code (LOC):                   264677
Comment Lines of Code (CLOC):          137050
Non-Comment Lines of Code (NCLOC):     127627

Interfaces:                               103
Classes:                                 1712
Non-Static Methods:                      5697
Static Methods:                           585
Functions:                                944
Jeweils nur das library-verzeichnis, also ohne unittests, code-beispiele etc.

Die meisten objekt-orientierten Systeme wie ezComponents, Zend Framework, Symfony, Doctrine und co, würde ich auch nicht bei Projekten einsetzen wollen die später auf einem kleinen 08/15 Webspace laufen, schon weil man dort keinen Byte-Code-Cache hat, was die Performance ziemlich drosseln kann und wo man auch mal schneller an memory-limits von 8 oder 12 MB rankommt, aber die Entwicklungszeit und die Erweiterbarkeit (auch die fertigen Code-Schnipsel und erweiterungen die man zu den Systemen im Web findet) sind einfach großartig.


Zitat:
Ich muss allerdings nochmal nachhaken, was das "Profiling" angeht. Wie genau überprüfst du denn, ob du performant oder eben nicht arbeitest?
Klar, ich könnt mir da jetzt entsprechende Vergleichsskripte schreiben etc., aber das ist ja dann doch ein enormer Zusatzaufwand, der im Bezug auf das Ergebnis eventuell gerechtfertigt sein kann, aber ja nicht unbedingt sein muss. ;)
Betreffs Profiling: Der Profiler ist ein bei Zend_Db und auch bei Doctrine aktivierbares Plugin das sämtliche ausgeführten Querys aufzeichnet, dass man eben sieht wie viele werden ausgeführt, wie lange brauchen sie ... etc.

Wenn du in einer Zend Framework basierten Umgebung arbeitest kann ich dir die ZFDebug empfehlen, das ist eine Art Toolbar in Form eines Plugins für den FrontController das ein paar nützliche Daten anzeigt.

Ich hab mir dazu irgendwann mal als Ersatz für Zend_Db ein Plugin für Doctrine geschrieben das mit den Profiler von Doctrine nutzt und alle Infos über Querys anzeigt, hier gibt es für ZFDebug so ein Plugin für Doctrine: http://www.danceric.net/2009/06/06/z...-doctrine-orm/ .

So sieht das dann beispielsweise aus:
Bild: http://www.ld-host.de/uploads/images...460d8e99b6.png

Hier sieht man dann schon recht schnell ob eben irgendwo die Relationen jedes mal extra abgerufen werden oder das sauber in einem Query passiert.

Neben Nutzung eines Caches, Speicherverbrauch, Execution-Time, geladenen Dateien und einigen anderen Infos kann man dann eben auch Informationen des Profilers für die Querys anschauen und sieht welche Querys ausgeführt wurden.
Allerdings nicht gleich von hohen zahlen abschrecken lassen, nicht alles sind querys an die datenbank, es werden auch andere Sachen mit erfasst.

Geändert von robo47 (26.08.2009 um 15:39 Uhr)
robo47 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 26.08.2009, 14:38 Nach oben    #5
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Koblenz
Beiträge: 4.794
Standard

Danke sehr. Werde mir die Profiling-Tipps mal anschauen.
Mir geht es hier gar nicht so sehr um den praktischen Einsatz, sondern eher darum zu lernen, wie man mit Doctrine umgeht.

Deine Anmerkungen haben mir da schon sehr weitergeholfen.
Ich höre natürlich auch gerne andere Meinungen .. Meinungsvielfalt kann in diesem Bereich nur sinnvoll sein.
__________________
Mehr TuS Koblenz geht nicht ... - TuS Koblenz Forum ... Benjamin Klaile ist noch in der Aufwärmphase
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 07.09.2009, 00:01 Nach oben    #6
:D
 
Benutzerbild von bobby
 
Registriert seit: 09.03.2007
Ort: Nürnberg
Beiträge: 81
Standard

robo47: Hast du die Möglichkeit dein Projekt mal mit einer "kompilierten" Version von Doctrine zu testen? Ist ein Performance-Gewinn spürbar?

Doctrine ORM for PHP - Compile
__________________
Viele Grüße,
bobby.
bobby ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 07.09.2009, 08:20 Nach oben    #7
Benjamin Steininger
 
Benutzerbild von robo47
 
Registriert seit: 02.06.2005
Ort: weiher im tiefsten Odenwald
Beiträge: 1.379
Standard

Das hab ich anfangs auch durchgetest, die Performance war gerade auf Seiten wo mehr mit Doctrine gemacht wird ein Stück besser, auf manchen wo man nur minimal brauchte war es dann langsamer, aber es ging stark zu Lasten des Speicherverbrauchs (glaub waren damals 2 oder 3 MB mehr) und APC cacht die Datei dann auch nur wenn man explizit das Dateigrößen-Limit hochsetzt, weil das normalerweise bei 1MB liegt.

Da ich aktuell noch auf einer Kiste mit nur 512 MB RAM bin (Darauf laufen aktuell schon 2 Webservern, Datenbankserver, Mailserver, VPN-Server, Jabber-Server und bissel kleinkram) ist mir das zu viel Speicher mehr bei jedem Scriptaufruf gewesen, beim neuen Server hab ich 8GB da werde ich mir das ganze wieder anschauen, der ist halt auch vom Rest her ein gutes Stück schneller :)
robo47 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2009, 21:46 Nach oben    #8
Benjamin Steininger
 
Benutzerbild von robo47
 
Registriert seit: 02.06.2005
Ort: weiher im tiefsten Odenwald
Beiträge: 1.379
Standard

Hier hab ich mal eine Sammlung von Seiten, Code-Schnipsel und Bibliotheken angefangen für die Integration von Doctrine in eine Zend-Framework-Applikation, vielleicht interessiert das ja den ein oder anderen.

Articles, Snippets and Libraries for using Doctrine with the Zend Framework
robo47 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 20.01.2010, 14:57 Nach oben    #9
Ben
Erfahrener Benutzer
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Koblenz
Beiträge: 4.794
Standard

Kann man auch mal lesen: Test Results on Memory Usage of Zend Framework and Doctrine with APC rvdavid: A Web Developer's Blog
__________________
Mehr TuS Koblenz geht nicht ... - TuS Koblenz Forum ... Benjamin Klaile ist noch in der Aufwärmphase
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus



Alle Zeitangaben in WEZ +1. Es ist jetzt 07:01 Uhr.


Powered by vBulletin® Version 3.8.4 (Deutsch)
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47