RSS-Feed
Beiträge
Kommentare

Die Entscheidung war nun also gefallen: Ich wollte versuchen, auf Basis einer OXID CE ein brauchbares Projekterfassungs-Tool für uns zu programmieren. Die ersten Schritte dorthin hätte ich gerne im Rahmen der OXID Commons 2010 mit euch im Rahmen eines Workshops nachvollzogen. Nun versuche ich, das Ganze hier lesbar aufzubereiten.

oxid4project Login Screen

oxid4project Login Screen

Der Beitrag insgesamt verfolgt damit folgende Ziele:

  1. einen generellen Einblick in das OXID Framework (OF) geben
  2. zeigen, dass man damit nicht nur Onlineshops programmieren kann
  3. hilfreiche Tipps geben für den Umgang mit dem OF, die auch im Rahmen von Shops sehr nützlich sind. ;-)
 

Am Anfang steht das Konzept: Welche Grundelemente werden benötigt?

Es macht so gut wie nie Sinn, einfach drauf los zu coden - vor allem dann nicht, wenn man ein vorhandenes Framework nutzen will. Um herauszufinden, welche Teile des Frameworks sich am sinnvollsten für die eigene Applikation nutzen lassen, sollte man zunächst die benötigten Grundelemente definieren. Diese Definition soll dabei so erfolgen, dass jedes der genannten Grundelemente sich nach Möglichkeit bereits als Objekt denken lässt. Oder anders gesagt: Wir suchen nach klar abgrenzbaren Sach- und Funktionsbereichen in unserer geplanten Anwendung, die sinnvoll im Rahmen einzelner Klassen gekapselt werden können.

Für unsere Projekterfassung benötigen wir folgende Bereiche / Elemente:

  • Projekte: Projekt anlegen, löschen, editieren, auflisten ...
  • Mitarbeiter: anlegen, löschen, editieren, Login ... => OXID Userverwaltung
  • Erfassung von Arbeitseinheiten: Zeit- und Texterfassung, Bearbeitung von Einträgen, Löschen ...
  • Auswertungen: nur für Admin sicht- und nutzbar, über Frontend erreichbar (also nicht im Shop-Admin)

Aus dieser Definition ergibt sich ein Konzept für die benötigten Views und Templates sowie für sinnvolle Core-Objekte. Fangen wir pragmatisch mit den Views und Templates an:

 

Konzeption der Views und Templates

Die gesamte Anwendung soll im Endeffekt ja auf einem Webserver im Netz laufen, damit jeder Mitarbeiter das Tool nutzen kann, wo immer er sich auch gerade befindet. Also brauchen wir zunächst einmal einen Login-Bereich. Wie oben schon angedeutet, können wir hier komplett die OXID Standardfunktionalität der Benutzerverwaltung nutzen.
Als nächstes brauchen wir eine Zeit- und Texterfassungsmaske, in der die Mitarbeiter ein Projekt auswählen und eintragen können, wie lange sie daran gearbeitet haben und was genau sie in dieser Zeit gemacht haben.
Für die eigentliche Datenerfassung ist das schon alles. Allerdings will ich als Admin ja auch ein paar Auswertungsmöglichkeiten haben. Also fehlen noch folgende Views / Templates:

  • Listenseite(n) für Auswertungen (z. B.: alle noch nicht abgerechneten Projekte im Monat "X" etc.)
  • Detailseite für Auswertungen (z. B.: alle noch nicht abgerechneten Arbeitseinheiten von Projekt "Y" im Monat "X" etc.)
  • Detailseite für Bearbeitung von Einzeleinträgen, z. B. wegen Korrekturen, Abzug von nicht abrechenbaren Zeiten etc.
 

Let's code! - Login-Seite

Die Login-Seite ist im Grunde der einfachste Teil der gesamten Übung, weil wir hier zu nahezu 100% auf OXID Standardfunktionalität zurückgreifen können. Dennoch kann man bereits hier den ein oder anderen hilfreichen Tipp für den generellen Umgang mit dem OXID Framework unterbringen. Daher das Ganze nun etwas ausführlicher:

Wir brauchen eine View-Klasse und ein zugehöriges Template. Die View-Klasse gestaltet sich dabei ausgesprochen simpel:

class azprojectsLogin extends oxUbase
{
        /**
         * name of template file
         * @var str
         */
        protected $_sThisTemplate = "azprojectslogin.tpl";

        /**
         * calls parent (oxUbase) render and returns name of tpl file
         * @return str $this->_sThisTemplate
         *
         */
        public function render() {
                parent::render();

                return $this->_sThisTemplate;
        }
}

Jede View-Klasse im OF ist Extension der Klasse oxUbase. Wir verwenden diese Vererbung, um gewisse Grundmechanismen im OF automatisch mitnutzen zu können. Dabei ist zu beachten, dass eine View-Klasse dann auch immer eine public function render() besitzen muss, die a.) die parent::render() aufruft und b.) als return-Wert den Namen der Template-Datei zurückliefert.
Damit sind die Mindestanforderungen für eine eigene View-Klasse bereits erfüllt. Gesagt sei noch, dass der Dateiname der Klasse sinnvollerweise mit dem Klassennamen identisch sein - allerdings komplett in Kleinbuchstaben gehalten sein sollte. So vermeidet man Probleme beim Switch zwischen verschiedenen Betriebssystemen (z. B. Windows / Mac / BSD / Linux etc.).

Als nächstes machen wir uns nun an das Template heran. Dieses sollte am Ende in etwa so aussehen wie der Screenshot am Anfang dieses Beitrags (oxid4project Login-Screen).

Hier kommt es natürlich nicht auf das konkrete Layout an - das möge sich jeder so gestalten, wie es ihm gefällt. Ich möchte lediglich auf ein paar Grundzüge bei der Templategestaltung hinweisen.

Im OXID eShop besteht nahezu jede im Frontend sichtbare Seite aus mind. 6 Einzeltemplates, die in Form von includes eingebunden werden:

  1. something.tpl - Die Template-Datei, die von der aktuell aufgerufenen View-Klasse als return-Wert der render() function zurückgeliefert wird. Name ist natürlich für jede Seite anders. Hier erscheint der eigentliche Content der jeweiligen Seite.
  2. _header.tpl - Der Kopfbereich der Seite; wird innerhalb von something.tpl inkludiert.
  3. _footer.tpl - Der Fußbereich der Seite; wird innerhalb von something.tpl inkludiert.
  4. _path.tpl - Anzeige der Breadcrumb-Navigation.
  5. _left.tpl - Navigationsbereich auf der linken Seite; wird innerhalb von _header.tpl inkludiert.
  6. _right.tpl - Bereich für Aktionsboxen auf der rechten Seite; wird innerhalb von _header.tpl inkludiert.

Den größten Teil der Inhalte dieser OXID-Standardtemplatedateien benötigen wir für unser Projekt nicht. Also bauen wir uns stark vereinfachte eigene include-Dateien. Die generelle Nutzung des Grundschemas mit includes macht Sinn, da wir für unser kleines Tool ja auch eine ansprechende Optik wünschen und sich im Kopfbereich z. B. gut einige administrative Navigationspunkte unterbringen lassen, die damit dann automatisch auf jeder Seite sichtbar sind.

Einen speziellen Bereich auf der linken oder rechten Seite brauchen wir nicht, weshalb die entsprechenden includes komplett entfallen können. Dasselbe gilt für die Breadcrumb Navigation, die im Shop vor allem den Kategoriepfad nachbildet, den wir in unserer Anwendung überhaupt nicht benutzen.

Wie die Templates im einzelnen aussehen, kann sich jeder anhand der Beispieldateien selbst ansehen. (In Kürze möchte ich das Ganze als Projekt auf OXIDforge anlegen. Leider kann ich dort zur Zeit keinen Account erstellen ... daher gibt's die Dateien zunächst mal als Download hier im Blog. -> siehe Ende des Beitrags)

Hier sei nur erwähnt, dass ich mich für die aktuelle Anwendung entschieden habe, zwei eigene include-Dateien azprojectsheader.tpl und azprojectsfooter.tpl zu erstellen. In beiden Dateien ist nur das Nötigste enthalten. Auf ein paar Dinge möchte ich aber hinweisen:

dynamischer Seitentitel
Im Grunde soll jeder selbst entscheiden ob und welchen Seitentitel er für dieses Tool benutzen möchte. Ich habe mich daher dafür entschieden, den Shopnamen hier als dynamischen Wert einzusetzen, da dieser über den Shop-Adminbereich leicht änderbar ist. Die Einbindung sieht aus wie folgt:

Projekterfassung - [{$oxcmp_shop->oxshops__oxname->value}]

Das Objekt $oxcmp_shop ist dabei ein sog. Komponenten-Objekt. Die Komponenten sind besondere View-Klassen im OF, die in Form des Decorator Patterns bei jeder View-Klassen Instanziierung mitinstanziiert werden. Somit stehen Komponentenobjekte shop- bzw. applikationsübergreifend überall zur Verfügung. Das ist sehr nützlich und ich kann nur empfehlen, sich mit den OF Komponenten ein wenig genauer zu beschäftigen. Die entsprechenden Klassendateien finden sich alle im Verzeichnis views und die Dateinamen beginnen alle mit oxcmp_...
Es ist sogar relativ einfach möglich, beliebig viele eigene Komponenten in das OF einzubinden. Es würde den Rahmen dieses Beitrages sprengen, dies hier im Detail zu erläutern. Den erfahrenen OXID'lern sei ein Blick View-Klasse oxUbase empfohlen. Dort findet ihr unter den protected properties u. a. auch das Array namens $_aComponentNames. Direkt darunter findet sich ein leeres Array namens $_aUserComponentNames - hier können eigene Komponenten eingehängt werden - eine der vielfältigen Erweiterungsmöglichkeiten, die das OF von Haus aus anbietet.

Einbindung von Bildern
Bilder, die im Rahmen des Layouts benötigt werden, liegen im OF immer im Verzeichnis /out/basic/img. Dieser Pfad ist innerhalb der Templates abrufbar mittels der Methode $oViewConf->getImageUrl(). Es empfiehlt sich, diese Systematik beizubehalten, weil so auch später das Verlagern der Grafiken in einen anderen Pfad oder auf einen anderen Server sehr einfach zu realisieren ist, ohne gleich alle Templates ändern zu müssen.

HomeLink
Auf dem Logo oben links liegt - wie gemeinhin üblich - der Link zur Startseite unserer Anwendung. Im OF gibt es auch dafür eine eigene Methode, die innerhalb der Templates genutzt werden kann: $oViewConf->getHomeLink().

Sonstige Links
In der Templatedatei azprojectsheader.tpl finden sich einige Navigationslinks, die weitere (eigene) View-Klassen aufrufen sollen. Dies erfolgt innerhalb des OF generell via:

<a href="[{ $oViewConf->getSelfLink() }]cl=myclassname">Linktext</a>

wobei myclassname der Name der aufzurufenden View-Klasse ist.

Navigation nur für eingloggte User anzeigen

Die Navigation im Kopfbereich (Erfassung, Auswertung, Logout) sollte natürlich nur für eingeloggte User zu sehen sein. Dies erreichen wir sehr einfach über die folgende Abfrage im Template /out/basic/tpl/azprojectsheader.tpl:

[{ if $oxcmp_user->oxuser__oxpassword->value }]
...
[{ /if }]
 

Login-Funktionalität

Für die eigentliche Login-Funktionalität nutzen wir zu 100% OXID-Bordmittel. Das Login / Logout-Formular können wir komplett aus dem include-Template /out/basic/tpl/inc/cmp_login.tpl übernehmen. Der Klassenparameter, der in diesem Formular als hidden field "cl" übergeben wird, wird hier dynamisch mit der aktuell aufgerufenen View-Klasse gefüllt. Außerdem finden wir in dem Formular noch ein hidden field mit name="fnc" - dieses dient dazu, eine spezielle Methode auf der View-Klasse auszuführen. Der Name dieser Methode ist - je nach Zustand - login_noredirect oder logout.

In unserer View-Klasse azprojectslogin gibt es aber weder die eine noch die andere Methode. Das macht aber nichts - denn beide Methoden gehören zum Komponentenobjekt oxcmp_user und - wie oben schon erwähnt - stehen die Komponentenobjekte überall zur Verfügung. Und deshalb können wir auch die Methoden dieser Objekte an beliebiger Stelle aufrufen.

 

Umleitung der Startseite
Eine Kleinigkeit fehlt noch: Bisher bekommen wir noch immer die Startseite des Shops zu sehen, wenn wir unsere Anwendung ohne weitere Parameter aufrufen. Um das zu ändern legen wir ein kleines Modul der View-Klasse start an. Dazu erstellen wir eine Moduldatei mit dem Namen azstart.php mit folgendem Inhalt:

class azStart extends azStart_parent
{
        public function init()
    {
        header("location: index.php?cl=azprojectsstart");
    }

}

Diese Datei speichern wir nun unter: /modules/azstart/azstart.php. Anschließend rufen wir den Shop-Adminbereich auf (http://[Shopadresse]/admin/). Hier muss da Modul nun noch registriert werden: Admin --> Stammdaten --> Grundeinstellungen --> System --> Module. Dort bitte folgenden Eintrag tätigen:

start => azstart/azstart

und speichern. Nun wird jeder Aufruf der Shopstartseite auf die View-Klasse azprojectsstart umgeleitet. Diese existiert aber noch nicht und wird auch erst im dritten Teil dieses Workshops erläutert werden. Sie liegt aber dem Downloadpaket bereits - in abgespeckter Form - bei. Dort könnt ihr sehen, dass es auch in dieser Klasse innerhalb der Methode init() eine header-Weiterleitung auf die Login-Klasse gibt für den Fall, dass der User noch nicht eingeloggt ist.
Die Methode init() wird - nach einem evtl. vorhandenen constructor - immer als erste in einer View-Klasse ausgeführt.

 

Die Grundlage ist geschaffen

Bis hierher haben wir nun also die Grundlage für das geplante Tool geschaffen. Es fehlt noch die eigentliche Funktionalität - die ich in Teil 3 dieses Workshops präsentieren möchte. Aber ich denke, man konnte bis hier her bereits eine Ahnung dafür entwickeln, dass das OF viele Möglichkeiten für eigene Entwicklungen bietet. Diesem Beitrag hängt nun auch der erste Teil des Quellcodes des Projektes an, so dass die oben beschriebenen Punkte direkt nachvollzogen werden können.

Mit dem dritten Teil werde ich dann den kompletten Quellcode des Projektes liefern - vielleicht dann ja schon als OXIDforge-Projekt. Hier schon einmal ein Vorab-Happen: oxid4project_source_part_1