Ein CMS-Element aus einem Theme hinzufügen
Ein CMS-Element ist ein wiederverwendbarer Inhaltsblock, den der Admin auf einer CMS-Seite platzieren kann: ein Hero, ein Feature-Raster oder ein Testimonial-Slider. hostware liefert mehrere zentrale Elemente mit, und ein Theme kann eigene hinzufügen, indem du eine PHP-Klasse unter Cms/Elements/ sowie drei View-Dateien ablegst. Eine Registrierung ist nicht erforderlich. Das Element kann im Admin ausgewählt werden, sobald ein Sales Channel, der dein Theme verwendet, eine CMS-Seite lädt.
Das evolution theme verwendet diesen Mechanismus für seine evo_*-Elemente (Header, Zahlen, Feature-Boxen, Testimonials und so weiter) und dient als Referenzimplementierung, von der du kopieren kannst.
Die vier benötigten Dateien
Jedes CMS-Element besteht aus einer PHP-Klasse und drei View-Dateien mit einem übereinstimmenden Namensschema.
custom/themes/hw/mytheme/
├── Cms/
│ └── Elements/
│ └── My_Hero.php the element class
└── resources/
└── views/
└── cms/
└── elements/
├── my_hero.twig storefront output
├── my_hero_preview.blade.php admin preview thumbnail
└── my_hero_previewConfig.blade.php admin config formDie Namen müssen zusammenpassen. Der Dateiname der PHP-Klasse verwendet PascalCase mit einem Unterstrich als Präfix, der dem kleingeschriebenen Elementnamen entspricht (My_Hero => my_hero). Twig- und Blade-Dateien verwenden die snake_case-Form.
Die Elementklasse
Jedes Element implementiert App\Framework\Core\Cms\CmsElementInterface. Sechs Methoden, alle schlank.
<?php
// custom/themes/hw/mytheme/Cms/Elements/My_Hero.php
namespace custom\themes\hw\mytheme\Cms\Elements;
use App\Framework\Core\Cms\CmsElementInterface;
class My_Hero implements CmsElementInterface {
public function getName(): string {
return "my_hero";
}
public function getLabel(): string {
return "My Hero";
}
public function getView(): string {
return "theme.mytheme::cms/elements/my_hero";
}
public function getPreview(): string {
return "theme.mytheme::cms/elements/my_hero_preview";
}
public function getDefaultConfig(): array {
return [
"variant" => "left",
"title" => "Welcome",
];
}
public function provideData(array $config): array {
return $config;
}
}Der Namespace muss exakt dem Ordnerpfad entsprechen, wobei Vendor und Name kleingeschrieben werden (custom\themes\hw\mytheme\Cms\Elements). Die Elementerkennung durchläuft den Ordner Cms/Elements/ jedes aktiven Themes und instanziiert jede Klasse, die das Interface implementiert. Ein falscher Namespace bedeutet daher, dass das Element stillschweigend nie angezeigt wird.
Verwendung der einzelnen Methoden
getName()ist die eindeutige Element-ID, die in der Datenbankzeile des CMS-Elements gespeichert wird. Benenne sie niemals um, nachdem Benutzer sie verwendet haben, sonst verschwinden deren Inhalte.getLabel()ist das, was der Admin in der Elementauswahl sieht.getView()gibt das im Storefront gerenderte Twig-Template zurück. Verwende den Namespacetheme.<name>::, damit der Resolver innerhalb deines Themes bleibt.getPreview()gibt die kleine Vorschau zurück, die im CMS-Builder im Admin gerendert wird (Blade-Template).getDefaultConfig()legt die Konfigurationswerte an, wenn der Admin das Element zum ersten Mal platziert. Die hier zurückgegebenen Schlüssel sind diejenigen, die dein Storefront-Twig sicher auslesen kann.provideData(array $config)erhält die gespeicherte Konfiguration und gibt das Datenarray zurück, das dem Twig-Template zur Verfügung gestellt wird. Gib für ein zustandsloses Element einfach$configunverändert zurück. Wenn das Element aktuelle Werte benötigt (etwa eine Produktliste oder einen Kategoriebaum), füllst du die Daten mit Modelldaten.
Das Storefront-Twig-Template
Das von getView() gerenderte Template erhält alles, was provideData() zurückgegeben hat, als Variablen auf oberster Ebene. Es gibt keinen umschließenden Block-Scope. Daher funktioniert {{ config.title }}, wenn dein provideData ['config' => $config] zurückgegeben hat, oder {{ title }}, wenn es ['title' => $config['title']] zurückgegeben hat.
{# resources/views/cms/elements/my_hero.twig #}
<section class="my-hero variant--{{ config.variant ?? 'left' }}">
<div class="hw-container">
{% if config.title %}
<h1>{{ config.title|raw }}</h1>
{% endif %}
</div>
</section>Umschließe den Inhalt mit .hw-container, wenn er an der 1200px breiten Inhaltsfläche des restlichen Storefronts ausgerichtet werden soll. Lass es für Bereiche über die gesamte Breite weg.
Die Admin-Vorschau und das Konfigurationsformular
Beide Admin-Dateien sind Blade und nicht Twig, da der Admin Blade-Views verwendet. Lass die Vorschau-Datei leer, wenn das Admin-Miniaturbild nicht wichtig ist, und beschränke die Konfigurationsdatei auf die Einstellungen, die der Admin tatsächlich benötigt.
{{-- my_hero_previewConfig.blade.php --}}
<div class="form-group">
<label>Variant</label>
<select class="form-control custom-select" name="config['variant']">
<option value="left" selected>Left</option>
<option value="centered">Centered</option>
</select>
</div>
<div class="form-group">
<label>Title</label>
<input type="text" class="form-control" name="config['title']" value="{{ $config['title'] ?? '' }}">
</div>Input-Namen verwenden immer die Klammerform config['key']. Alles, was du hier einträgst, wird in das JSON der Konfiguration geschrieben, das der Admin in der Elementzeile speichert. Genau diese Konfiguration erhält dein provideData() beim nächsten Rendern.
SCSS mit dem Element ausliefern
Elemente können eigenes SCSS enthalten. Füge ein Partial unter public/css/elements/ hinzu und importiere es in deiner style.scss:
// public/css/style.scss
@import "elements/my_hero";Die Kompilierung pro Sales Channel übernimmt das neue Partial beim nächsten Speichern des Brandings oder beim nächsten theme:watch-Tick.
Boolean-Checkboxen werden nur gesendet, wenn sie aktiviert sind. Lies sie im Twig-Template mit {% if config.my_flag is defined %} aus, niemals mit == true, außer getDefaultConfig() gibt standardmäßig false für sie zurück.