Skip to content

Craft CMS ​

Projekt aufsetzen ​

  1. Github repository auf Basis der Vorlage anlegen, mit Name domain.tld
  2. Git repository in VS Code clonen
  3. In .ddev/config.yaml bei name: den Projektnamen setzen, etwa domain-tld
  4. In 1Password ein eigenes Environment für das Projekt anlegen (Werte nach .env.example) und seine ID im pre-start-Hook in .ddev/config.yaml eintragen, anstelle der ID der Vorlage. Mit der ID der Vorlage bricht ddev start in einer Kopie ab.
  5. colima start
  6. ddev start
  7. ddev npm install
  8. ddev ssh
  9. composer install --no-interaction
  10. mysql db < dump.sql
  11. exit
  12. ddev launch, /redaktion im Browser anhängen
  13. Site language üblicherweise de-CH
  14. Admin login xxx-admin mit xxx = Kundenkürzel

Dateipfade ​

Nutze für alle Dateipfade die in der config/general.php angelegten Aliase.

Nomenklatur ​

Datenquellen ​

pfad-…-pfad-bereich

Der letzte Namensbestandteil nennt den Namen des Bereichs und sagt somit , welche Daten die Datenquelle enthält.

Die Bestandteile zuvor TODO

Felder ​

Es kann sinnvoll sein, ein einmal angelegtes Feld mehrfach zu benutzen. Allerdings kann es sein, dass man später einmal an einer Stelle im Backend etwas dokumentieren will (Default Instructions). Diese instruction erscheint dann überall, wo das Feld verwendet wird. Denke daher inhaltlich, ob eine Mehrfachnutzung sinnvoll ist.

Feldnamen ​

Feldnamen im CMS (zum Beispiel ‹Titel›) und deren Klasse im HTML sollen gleich heissen (<h2 class="veranstaltung__titel">).

Der Feldname soll nicht wiederholen, was bereits durch den Kontext erkennbar ist. Ein Beispiel: Heisst die Section ‹Abschnitte› heisst das Feld für den Abschnittstitel nur ‹Titel›, nicht etwa ‹Abschnittstitel›.

  • Titel
  • Untertitel
  • Kurztitel
  • Beschreibung
  • Text
  • Bild
  • Spalte, Spalte x
  • E-Mail
  • PLZ, PLZ & Ort
  • Strasse & Nummer
  • Telefon
  • Mobil

Relationale Bezüge ​

Es ist naheliegend, relationale Bezüge (in Symphony CMS ‹Association›) auf den Titel eines Datensatzes zu setzen. Das hat zwei Nachteile:

  • Einträge gleichen Namens werden in der URL zu titel und titel-2
  • Das Dropdown/die Suche, um eine Verknäpfung herzustellen zeigt nur den Titel

In vielen Fällen ist es sinnvoll, ein zusätzliches Feld anzulegen, das automatisch einen besser lesbaren Namen erzeugt (in Symphony CMS ‹Reflection›). Beispiele:

  • Im Newsletter des Theaters am Bahnhof wählt ein Redakeur Veranstaltungen aus und sieht dabei nicht nur den Titel der Veranstaltung, sondern auch den Archivstatus und ob Bühne oder Atelierkino
  • Beim Theater am Banhof zeigt die URL zusätzlich zum Namen der Veranstaltung, dass es ein Special ist, so dass die Veranstaltung ohne Special und das Special nicht so aussehen: veranstaltungstitel-2 (nicht im Projekt umgesetzt)

Mailversand über Trigger ​

Ist der Trigger das Anlegen eines neuen entry, löst der Trigger zwei Mal aus. Das ist, weil Craft zuerst einen Draft/Revision anlegt und dieser ein eigenständiger entry ist. Der Trigger benötigt daher zwei Filter: is not a draft und is not a revision. Das ist dokumentiert in einem issue des trigger Plugins.

Soll die Mail nur versendet werden, wenn der enry neu angelegt wird, braucht es zusätzlich den Filter is new. Das gilt, wenn nur das Anlegen per Frontend triggern soll, nicht aber das händische Ändern durch einen Redakteur.

Staging/Production ​

Dotenv ​

Die Dotenv braucht auf dem Server andere Werte für die Datenbankverbindung und für alle URLs. Die .env.example im template repository nennt bei jedem Schlüssel, was dort anders lautet.

Sonderfall: Zugangsdaten im JavaScript ​

Projekte mit Vue.js kompilieren Zugangsdaten in das JavaScript, etwa einen Craft-User oder ein GraphQL-Token. Der Build läuft auf dem Entwicklungssystem und liest dort die lokale Dotenv – das Ergebnis enthielte also die Werte von dev.

Eine eigene Dotenv für den Build braucht es nur, wenn sich diese Werte zwischen dev, staging und production unterscheiden. Sie heisst nach dem Modus des Builds, .env.production oder .env.staging, liegt auf dem Entwicklungssystem und wird von Vite beim Build automatisch gelesen. Sind die Werte überall gleich, genügt die eine Dotenv.

Cronjobs einrichten ​

Die automatische Ausführung der Craft Queue ist in der config deaktiviert. Statdessen braucht es Cronjonbs im Hosting:

Craft Queue ​

Häufigkeit *****

/usr/bin/bash /home/ANMELDENAME/public_html/ORDNERNAME/cronjobs/craft-queue.sh

Blitz ​

Häufigkeit 5****

/usr/bin/bash /home/ANMELDENAME/public_html/ORDNERNAME/cronjobs/blitz-cache-expired.sh

Craft Updates ​

Updates werden nur lokal (Umgebung development) durchgeführt. Die Datei composer.jsonmuss für Updates gemäss SemVer vorbereitet sein: Versionen brauchen eine Erlaubnis zum Update mit ^3.5.2 statt 3.5.2 (^ minor updates, ~ patch update).
https://nystudio107.com/blog/updating-craft-cms-without-headaches

console
ddev ssh
composer self-update
composer update
php craft up

Craft Plugins ​

Plugins können über die Weboberfläche installiert werden, aber nur darüber deinstalliert werden, nicht gelöscht. Um ein Plugin ganz zu löschen sind folgende Schritte nötig:

  1. Das Plugin aktivieren (nur aktive können deinstalliert werden)
  • über die Weboberfläche
  • über SSH: ./craft plugin/enable plugin-handle
  1. Das Plugin deinstallieren
  • über die Weboberfläche
  • über SSH: ./craft plugin/uninstall plugin-handle
  1. Das Plugin via SSH und Composer löschen: composer remove namespace/package-name

Der package-name steht in Github und auch in der composer.json

Craft Probleme ​

CKEditor erzeugt SQLSTATE[42S22]: Column not found ​

Dieser Fehler ist bisher direkt nach Aufsetzen eines neuen Projekts aufgetreten, wenn ein Feld vom Typ CKEditor angelegt wird. Die Deinstallation des Plugins hilft nicht. Stattdessen muss die Datenbank neu erzeugt werden:

console
ddev delete --omit-snapshot
ddev start
ddev ssh
php craft setup

CKEditor ​

Um Testen (p, h1, h2, …) eine Klasse zu geben, braucht es folgenden Code. Wichtig: Das Model darf nicht paragraph und und heading1 usw. heissen, sondern muss von den Standardnamen abweichen. In der JSON Ansicht wird das als Fehler markiert («Value is not accepted. Valid values: "heading1", "heading2", …», es funktioniert aber.

class gibt dem Button im CKEditor eine Class, um den Button gestalten zu können. view.classes sind die Klassen, die dem Text zugewiesen werden (bereits im CKEditor und vor allem im Frontend).

js
return {
  heading: {
    options: [
      {
        class: 'module-text__lead-ck',
        model: 'paragraph-leq',
        title: 'Paragraph',
        view: {
          classes: 'module-text__lead',
          name: 'p',
        },
      },
      {
        class: 'module-text__heading--2-ck',
        model: 'heading2-leq',
        title: 'Titel',
        view: {
          classes: 'module-text__heading--2',
          name: 'h2',
        },
      },
    ],
  },
  link: {
    decorators: {
      openInNewTab: {
        attributes: {
          rel: 'noopener noreferrer',
          target: '_blank',
        },
        label: 'Open in new tab?',
        mode: 'manual',
      },
    },
  },
  style: {
    definitions: [
      {
        classes: [
          'module-text__inlinelink',
        ],
        element: 'p',
        name: 'Link mit Pfeil',
      },
    ],
  },
}