Blog

Was mich so beschäftigt...


Ein October CMS Plugin erstellen

Dieser Beitrag zeigt dir, wie einfach und schnell du ein eigenes Plugin in October CMS erstellen kannst.

Was du dafür brauchst ist eine lauffähige Instanz von October idealerweise lokal um einfach Dateien editieren zu können.

Ausserdem verwende ich jeweils das Builder Plugin von Rainlab. Mit diesem kann über ein GUI ein Grossteil des Plugins erstellt werden.

Ich gehe davon aus, dass du dich mit OOP und MVC auskennst.

Vorbereitungen

In diesem Beispiel erstelle ich ein Plugin um Rechnungen in October schreiben und generieren zu können.

Mein Datenbankschema soll in ungefähr so aussehen.

Datenbankschema

Das ist natürlich sehr rudimentär, aber für den Anfang reicht es.

Wenn ich im October nun also das Builder Plugin installiert habe, habe ich im Menu oben einen entsprechenden Menupunkt.

Wenn ich das Plugin zum ersten mal oder in einem neuen Projekt verwende, muss ich noch in den Einstellungen meinen Namen und Namespace definieren.

Menupunkt für die Builder Einstellungen

Einstellungen für Name und Namespace

Danach kann ich den Builder öffnen und zuerst ein Plugin auswählen respektive ein neues erstellen.

Dazu wähle ich auf der linken Seite den Pfeil.

Menu um Plugin zu wählen

Über Create Plugin erstelle ich nun mein Plugin und mache einige grundsätzlichen Angaben dazu. Standardmässig zeigt die Liste nur eigene Plugins an, das heisst Plugins im oben angegebenen Namespace. Über das Filter/Trichter-Symbol kann dies umgeschaltet werden.

Ist das Plugin erstellt und ausgewählt können wir mit dem Database-Reiter beginnen um unsere Tabellen zu erstellen.

Datenbanktabelle erstellen

Neue Tabelle erstellen

Für den Namen ist der Namespace und Pluginname bereits drin. Ergänze den Namen deshalb um den Tabellennamen. Ich habe in diesem Fall aramloosman_billing_bills gewählt. Somit komme ich in keinen Konflikt mit anderen Tabellen in der Datenbank.

Als nächstes gehts um die Spalten. In der Zeile oberhalb der Tabelle gibt es einige Shortcuts (Add ID, Add timestamps, Soft deleting etc), welche ich immer verwende.

Danach können weitere Spalten erfasst werden.

Die Reihenfolge der Spalten lässt sich nachträglich leider nicht mehr verändern.

Komplette Tabelle

Ich habe statt einzelne Adressfelder nur die ID einer Person hinzugefügt. Diese verweist auf ein Model in einem anderen Plugin. Es könnten hier aber auch einfach einzelne Felder mit Vor- und Nachname, Adresse etc. hinzugefügt werden. Ausserdem habe ich noch ein Statusfeld eingefügt.

Dasselbe mache ich nun mit der andere Tabelle, welche bei mir aramloosman_billing_billitem heisst.

Komplette Tabelle für Rechnungszeile

Folgende Punkte sind zu beachten:

  • Referenz Rechnungstabelle
    Die bill_id verweist auf die Rechnungstabelle. Sie setzt sich aus dem Namen des Models und _id zusammen.
  • Reihenfolge / Zeilennummer
    Das Sortieren der Zeilen kann October übernehmen. Dazu habe ich die Spalte sort_order eingefügt. Ich nutze dieselbe Spalte um die Zeilennummer auszugeben. Diese Spalte muss als Standardwert 0 haben.

Ich habe bewusst darauf verzichtet zu diesem Zeitpunkt weiter Spalten hinzuzufügen. Wahrscheinlich kommt dann später noch Sachen wie Anzahl, Einheit, Stückpreis etc. hinzu.

Models erstellen

Als nächstes können die Models erstellt werden.

Formular zum erstellen eines Models

Dieser Schritt ist eigentlich selbsterklärend. Der Modelname muss in diesem Fall mit vorher erstellter Referenzspalte bill_id übereinstimmen, also Bill.

Die beiden Checkboxen können angewählt werden, wenn die entsprechenden Spalten vorher hinzugefügt wurden.

Hinzufügen eines Model-Forms

Über das + neben Forms und Lists kann das Backend-Formular, respektive die Liste erstellt werden.

Hier erfassen wir sämtliche Felder, welche im Formular angezeigt werden.

Formular zur erstellung des Backend-Formulars

Hier habe ich den Status mal als Textfeld und das Rechnungsdatum als Date picker hinterlegt.

Der Kunde ist vom Typ Relation, dazu später mehr.

Formular zur erstellung der Listenansicht

In der Listenansicht habe ich die beiden Felder hinzugefügt.

Dasselbe erfolgt jetzt noch für das Billitem Objekt. Ein Eingabefeld für bill_id kannst du zu diesem Zeitpunkt weglassen.

Permissions

Die Permissions lasse ich jetzt mal weg.

Backend Menu

Der Menupunkt für das Backend

Der Code muss ein eindeutiger String sein.

Die URL besteht aus Namespace, Pluginname und Name des Controllers. Dies ist etwas undurchsichtig, da der Controller erst im nächsten Schritt erstellt wird.

Du kannst aber auch einfach den Menupunkt erst danach erstellen.

Für die Billitems erstellen wir keinen eigenen Menupunkt, die sollen ja innerhalb der Rechnung angezeigt werden. Es wäre aber ohne weiteres Möglich!

Controller

Dem Controller geben wir einen sprechenden Namen, welcher auch im Backendmenu referenziert wird.

Erstellen eines Controllers

Wir wählen das Model aus, welches der Controller verwaltet.

Der aktive Menupunkt kann rechts ausgewählt werden. Dies steuert nur, welcher Menupunkt als aktiv markiert ist. Wenn du den Menupunkt noch nicht erstellt hast, musst du das später in der Controller-Datei selbst tun.

Ausserdem wählen wir welches Verhalten der Controller implementieren soll.

Hier wähle ich Liste und Formular.

Nach erfolgreichem Speichern und neuladen der Seite sollte jetzt ein Menupunkt erscheinen, über welchen du eine leere Liste erhältst.

Relationen

Nun haben wir eine sehr simple Form um Daten aufzulisten und zu bearbeiten. Allerdings ist die Relation zwischen Rechnung und Rechnungszeile noch nicht abgebildet.

Als erstes müssen wir im Model die Relation hinterlegen. Das Feld in der Tabelle existiert zwar, aber October weiss nicht, um welche Art von Relation es sich handelt.

Nun öffnen wir das Billitem-Model und fügen in der Klasse folgender Code hinzu:

public $belongsTo = [
    'bill' => [ 'AramLoosman\Billing\Models\Bill' ],
];

bill bezieht sich hier auf das intern verwendete Attribut für die Relation. Es zeigt auf den vollständigen Pfad inkl. Namespace der Bill-Klasse.

Im Bill-Model machen wir dasselbe, schreiben aber:

public $hasMany = [
    'billitems' => [ 'AramLoosman\Billing\Models\Billitem' ],
];

Damit funktioniert die Relation zwischen den beiden Models.

Relation im Backend

Wir möchten nun die Billitems aber gerne im Backend editieren können.

Dazu müssen wir etwas mehr Hand anlegen.

Nun muss ich den Bill-Controller noch anpassen.

Ich editiere also controllers/Billing.php.

In das Array $implement kommt der zusätzliche Eintrag

'Backend\Behaviors\RelationController',

Weiter unten setze ich wo die Konfiguration für die Relation zu finden ist.

    public $relationConfig = 'config_relation.yaml';

Diese Datei erstelle ich nun unter controllers/billing/config_relation.yaml und befülle sie folgendermassen:

billitems:
    label: Rechnungszeilen
    manage:
        form: $/aramloosman/billing/models/billitem/fields.yaml
        list: $/aramloosman/billing/models/billitem/columns.yaml
    view:
        list: $/aramloosman/billing/models/billitem/columns.yaml
        toolbarButtons: create|delete

Nun muss ich noch das Bill-Formular anpassen. Ich kann diese Änderung auch im Builder-Frontend machen, aber da ich schon in den Files bin mach ich es hier. Die Datei liegt in aramloosman/billing/models/bill/fields.yaml.

Hier füge ich ein Feld mit folgenden Werten hinzu:

    billitems:
        span: full
        path: ~/plugins/aramloosman/billing/controllers/billing/_billitems.htm
        type: partial

Dies fügt ein Formularelement vom Typ Partial hinzu. Partial bedeutet, dass einfach ein eigenes Template gerendert wird, in diesem Fall dasjenige welches über path angegeben wird.

In dieses File wird nur folgender Inhalt geschrieben:

<?= $this->relationRender('billitems'); ?>

Damit rendert October automatisch das, was in config_relation.yaml definiert ist.

Jetzt ist es möglich, die Rechnungen zu bearbeiten und Rechnungszeilen zu erfassen.

Reihenfolge ändern

Grundsätzlich ist es kein Problem die Sortierung von Models einzubauen, aber ich habe gemerkt dass es bei Unter-Models etwas komplizierter ist. Ich muss da noch einwenig Zeit investieren um das herauszufinden.

Veröffentlicht in Coding am 20.11.2019