Mutagen resetten und Mutagen deaktiveren
ddev mutagen reset && ddev config global --performance-mode=none && ddev config --performance-mode=noneBashMeine Gedankenstütze ;-)
Mutagen resetten und Mutagen deaktiveren
ddev mutagen reset && ddev config global --performance-mode=none && ddev config --performance-mode=noneBashIch habe dazu eine Videoserie von Stefan Frömken zusammengestellt. Stefan ist ein Urgestein der Typo3-Community und wer könnte besser über dieses Thema referieren.
Für die Initialisierung mit Composer wird die Extension b13/make benutzt.
Der Ablauf ähnelt dem Initialisierungsprozess mit NPM.
Zu beachten ist hier, ob mit DDEV entwickelt wird oder nicht!
Die Entwicklung der Extension wird im src/extensions – Verzeichnis empfohlen.
In der Composer.json – Datei im Projektroot empfiehlt sich ein Wildcard anzugeben. Damit muss man nicht für jede weitere Extension einen neuen Eintrag machen.
"repositories": [
{
"type": "path",
"url": "src/extensions/*"
}
],JSONAm Ende sollte die Extension im Typo3-Backend unter Extensions aufgeführt und aktiviert sein.
Die Datenbankstruktur wird in ext_tables.sql in der Extension angelegt.
CREATE TABLE tx_sales_campaign (
titel varchar(255) DEFAULT '' NOT NULL COMMENT 'Titel',
beschreibung varchar(255) DEFAULT '' NOT NULL COMMENT 'Beschreibung',
zuordnung varchar(255) DEFAULT '' NOT NULL COMMENT 'Zuordnung',
);
CREATE TABLE tx_sales_object (
bearbeitungsnummer varchar(20) DEFAULT '' NOT NULL COMMENT 'Bearbeitungsnummer',
titel varchar(255) DEFAULT '' NOT NULL COMMENT 'Titel',
preis float(30,2) NOT NULL COMMENT 'Preis in Euro',
preisart varchar(50) DEFAULT '' NOT NULL COMMENT 'Preisart (z.B. Mindestgebot, Festpreis, Verhandlungsbasis)',
beschreibung varchar(255) DEFAULT '' NOT NULL COMMENT 'Beschreibung der Kampagne',
bilder int(11) DEFAULT 0 NOT NULL COMMENT 'Bilder',
uploads int(11) DEFAULT 0 NOT NULL COMMENT 'Uploads',
tx_sales_campaign_uid int(10) DEFAULT 0 NOT NULL COMMENT 'Verknüpfung zur Kampagne',
);SQLÜber das Backend Verwaltungswerkzeuge > Wartung > Analyze Database Structure kann man die Tabellen anlegen oder Änderungen an der DB ausführen. Am besten man legt vorher noch das TCA an, damit auch dynamisch Spalten aus dem TCA gleich mit in der Tabelle angelegt werden. (bspw. crdate oder deleted etc.)
Für die Definition der Felder ist die TCA-Dokumentation unabdingbar.
Im Extensionordner legt man nun im Ordner EXT:sales/Configuration/TCA die Dateien tx_sales_campaign.php und tx_sales_objects.php an. Also für jede Tabelle eine eigene TCA.
<?php
/**
* TCA for the sales table and its fields in the backend
*/
return [
'ctrl' => [
'title' => 'Verkaufskampagnen',
'label' => 'titel',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'delete' => 'deleted',
'sortby' => 'sorting',
'default_sortby' => 'titel',
'versioningWS' => true,
'rootLevel' => 0,
//'iconfile' => 'EXT:styleguide/Resources/Public/Icons/tx_styleguide.svg',
'origUid' => 't3_origuid',
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent',
'transOrigDiffSourceField' => 'l10n_diffsource',
'translationSource' => 'l10n_source',
'searchFields' => 'titel,beschreibung',
'security' => [
'ignorePageTypeRestriction' => true,
],
'enablecolumns' => [
'disabled' => 'hidden',
'starttime' => 'starttime',
'endtime' => 'endtime',
],
],
'columns' => [
'titel' => [
'exclude' => true,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.campaign.titel',
'config' => [
'type' => 'input',
],
],
'beschreibung' => [
'exclude' => true,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.campaign.beschreibung',
'config' => [
'type' => 'text',
'cols' => 40,
'rows' => 5,
'eval' => 'trim',
],
],
'endtime' => [
'exclude' => false,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.campaign.anzeigen_bis',
'config' => [
'type' => 'input',
'renderType' => 'inputDateTime',
'eval' => 'datetime,int', // 'datetime' für die Benutzeroberfläche, 'int' für Speicherung als Timestamp
'default' => 0, // Standardwert ist 0
],
],
'starttime' => [
'exclude' => false,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.campaign.anzeigen_von',
'config' => [
'type' => 'input',
'renderType' => 'inputDateTime',
'eval' => 'datetime,int', // 'datetime' für die Benutzeroberfläche, 'int' für Speicherung als Timestamp
'default' => 0, // Standardwert ist 0
],
],
/* Show delete field */
'deleted' => [
'exclude' => true,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.campaign.deleted',
'config' => [
'type' => 'check',
'renderType' => 'checkboxToggle',
'items' => [
[
0 => '',
1 => '',
'invertStateDisplay' => true
]
],
],
],
'hidden' => [
'exclude' => false,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.enabled',
'config' => [
'type' => 'check',
'renderType' => 'checkboxToggle',
'items' => [
[
0 => '',
1 => '',
'invertStateDisplay' => true
]
],
]
],
],
'types' => [
[
'showitem' => 'titel, beschreibung, hidden, starttime, endtime, deleted',
],
],
];
PHP<?php
/**
* TCA for the sales table and its fields in the backend
*/
return [
'ctrl' => [
'title' => 'Verkaufsobjekte',
'label' => 'bearbeitungsnummer',
'label_alt' => 'titel',
'label_alt_force' => true,
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'delete' => 'deleted',
'sortby' => 'sorting',
'default_sortby' => 'bearbeitungsnummer',
'versioningWS' => true,
'rootLevel' => 0,
//'iconfile' => 'EXT:styleguide/Resources/Public/Icons/tx_styleguide.svg',
'origUid' => 't3_origuid',
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l10n_parent',
'transOrigDiffSourceField' => 'l10n_diffsource',
'translationSource' => 'l10n_source',
'searchFields' => 'titel,bearbeitungsnummer,beschreibung',
'security' => [
'ignorePageTypeRestriction' => true,
],
'enablecolumns' => [
'disabled' => 'hidden'
],
],
'columns' => [
'bearbeitungsnummer' => [
'exclude' => true,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.bearbeitungsnummer',
'config' => [
'type' => 'input',
],
],
'tx_sales_campaign_uid' => [
'exclude' => true,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.kampagne',
'config' => [
'type' => 'select',
'renderType' => 'selectSingle',
'foreign_table' => 'tx_sales_campaign', // Tabelle für die Kampagnen
'maxitems' => 1, // Da es eine 1:n Beziehung ist
],
],
'titel' => [
'exclude' => true,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.titel',
'config' => [
'type' => 'input',
],
],
'beschreibung' => [
'exclude' => true,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.beschreibung',
'config' => [
'type' => 'text',
'cols' => 40,
'rows' => 5,
'eval' => 'trim',
],
],
'preis' => [
'exclude' => true,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.preis',
'config' => [
'type' => 'number',
'size' => 10,
'format' => 'decimal',
'eval' => 'double,required', // 'double' für Gleitkommazahlen, 'required' für Pflichtfeld
'placeholder' => 'z.B. 99.99', // Hinweistext im Eingabefeld
],
],
'preisart' => [
'exclude' => true,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.preisart',
'config' => [
'type' => 'select',
'renderType' => 'selectSingle',
'items' => [
['Mindestangebot', 'Mindestangebot'],
['Festpreis', 'Festpreis'],
['Verhandlungsbasis', 'Verhandlungsbasis']
],
'default' => 'Festpreis', // Optional: Standardwert festlegen
],
],
'bilder' => [
'exclude' => true,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.bilder',
'config' => [
'type' => 'inline',
'foreign_table' => 'sys_file_reference',
'foreign_field' => 'uid_foreign',
'foreign_sortby' => 'sorting_foreign',
'foreign_table_field' => 'tablenames',
'foreign_match_fields' => [
'fieldname' => 'bilder',
],
'foreign_label' => 'uid_local',
'foreign_selector' => 'uid_local',
'overrideChildTca' => [
'columns' => [
'uid_local' => [
'config' => [
'appearance' => [
'elementBrowserType' => 'file',
'elementBrowserAllowed' => 'jpg,jpeg,png,gif',
],
],
],
],
],
'filter' => [
[
'userFunc' => \TYPO3\CMS\Core\Imaging\IconFactory::class . '->getFilePickerFilter',
'parameters' => [
'allowedFileExtensions' => 'jpg,jpeg,png,gif',
],
],
],
'maxitems' => 5, // Maximale Anzahl der hochladbaren Bilder
'appearance' => [
'collapseAll' => true,
'showSynchronizationLink' => true,
'showAllLocalizationLink' => true,
],
],
],
'uploads' => [
'exclude' => true,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.uploads',
'config' => [
'type' => 'inline',
'foreign_table' => 'sys_file_reference',
'foreign_field' => 'uid_foreign',
'foreign_sortby' => 'sorting_foreign',
'foreign_table_field' => 'tablenames',
'foreign_match_fields' => [
'fieldname' => 'uploads',
],
'foreign_label' => 'uid_local',
'foreign_selector' => 'uid_local',
'overrideChildTca' => [
'columns' => [
'uid_local' => [
'config' => [
'appearance' => [
'elementBrowserType' => 'file',
'elementBrowserAllowed' => 'pdf',
],
],
],
],
],
'filter' => [
[
'userFunc' => \TYPO3\CMS\Core\Imaging\IconFactory::class . '->getFilePickerFilter',
'parameters' => [
'allowedFileExtensions' => 'pdf',
],
],
],
'maxitems' => 5, // Maximale Anzahl der hochladbaren PDFs
'appearance' => [
'collapseAll' => true,
'showSynchronizationLink' => true,
'showAllLocalizationLink' => true,
],
],
],
'endtime' => [
'exclude' => false,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.anzeigen_bis',
'config' => [
'type' => 'input',
'renderType' => 'inputDateTime',
'eval' => 'datetime,int', // 'datetime' für die Benutzeroberfläche, 'int' für Speicherung als Timestamp
'default' => 0, // Standardwert ist 0
],
],
'starttime' => [
'exclude' => false,
'label' => 'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.anzeigen_von',
'config' => [
'type' => 'input',
'renderType' => 'inputDateTime',
'eval' => 'datetime,int', // 'datetime' für die Benutzeroberfläche, 'int' für Speicherung als Timestamp
'default' => 0, // Standardwert ist 0
],
],
'hidden' => [
'exclude' => false,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.enabled',
'config' => [
'type' => 'check',
'renderType' => 'checkboxToggle',
'items' => [
[
0 => '',
1 => '',
'invertStateDisplay' => true
]
],
]
],
],
'types' => [
[
'showitem' => 'bearbeitungsnummer, tx_sales_campaign_uid, titel, beschreibung, preis, preisart, bilder, uploads, hidden, starttime, endtime',
],
],
];
PHPWenn über die Extension Datensätze angelegt werden sollen. Dann ist es am besten dafür einen gesonderten Systemordner anzulegen, in dem die Datensätze gespeichert werden sollen.
Über das Listenmodul kann man dann in dem Systemordner neue Datensätze anlegen.
Übersetzungen für Plugin, Felder etc. werden in folgendem Ordner angelegt EXT:Resources/Private/Language. Für Deutsch bspw: de.locallang_db.xlf.
Wie auf die Sprachen referenziert wird, sieht man im TCA. (bspw: LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.anzeigen_von)
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<xliff version="1.0">
<file source-language="en" datatype="plaintext" original="messages" date="2024-10-25T13:36:39Z"
product-name="sales">
<header/>
<body>
<!-- Kampagnen -->
<trans-unit id="tx_sales_sale.campaign.titel">
<source>Title</source>
<target>Titel</target>
</trans-unit>
<trans-unit id="tx_sales_sale.campaign.beschreibung">
<source>Description</source>
<target>Beschreibung</target>
</trans-unit>
<trans-unit id="tx_sales_sale.campaign.zuordnung">
<source>Assignment</source>
<target>Zuordnung</target>
</trans-unit>
<trans-unit id="tx_sales_sale.campaign.anzeigen_von">
<source>Publishing date</source>
<target>Veröffentlichungsdatum</target>
</trans-unit>
<trans-unit id="tx_sales_sale.campaign.anzeigen_bis">
<source>Expiry date</source>
<target>Ablaufdatum</target>
</trans-unit>
<!-- Verkäufe -->
<trans-unit id="tx_sales_sale.object.bearbeitungsnummer">
<source>processing number</source>
<target>Bearbeitungsnummer</target>
</trans-unit>
<trans-unit id="tx_sales_sale.object.titel">
<source>Title</source>
<target>Titel</target>
</trans-unit>
<trans-unit id="tx_sales_sale.object.preis">
<source>Price (in Euro)</source>
<target>Preis (in Euro)</target>
</trans-unit>
<trans-unit id="tx_sales_sale.object.preisart">
<source>Pricetype</source>
<target>Preisart</target>
</trans-unit>
<trans-unit id="tx_sales_sale.object.beschreibung">
<source>Description</source>
<target>Beschreibung</target>
</trans-unit>
<trans-unit id="tx_sales_sale.object.kampagne">
<source>Campaign</source>
<target>Kampagne</target>
</trans-unit>
<trans-unit id="tx_sales_sale.object.bilder">
<source>Images</source>
<target>Bilder</target>
</trans-unit>
<trans-unit id="tx_sales_sale.object.uploads">
<source>Documents</source>
<target>Dokumente</target>
</trans-unit>
<!-- Plugin -->
<trans-unit id="tx_sales_sale.pluginlabel">
<source>List sales</source>
<target>Verkäufe auflisten</target>
</trans-unit>
<trans-unit id="tx_sales_sale.plugindescription">
<source>List sales of campaings of the organisation</source>
<target>Füge dieses Plugin hinzu, um Verkäufe von Kampagnen der Organisation aufzulisten</target>
</trans-unit>
</body>
</file>
</xliff>
XMLUm Felder nur speziellen Benutzergruppen editierbar, anlegbar zur Verfügung zu stellen, muss im TCA an dem entsprechenden Feld exclude aus true gesetzt sein. Damit ist es per Default erstmal nicht verfügbar. Dann muss es in der Benutzergruppe in den Zugriffsrechten unter Erlaubte Ausschlussfelder explizit freigegeben werden.
Als erstes legt man unter EXT:sales/Configuration/TCA/Overrides eine Datei tt_content.php an. In dieser wird das Plugin registriert.
<?php
use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
ExtensionUtility::registerPlugin(
'Sales',
'list',
'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.pluginlabel',
'tx-sales-svgicon' // Has to be defined in EXT:Configuration/Icons.php
);
PHPDamit sollte das Plugin dann schon auswählbar sein. (Cache löschen nicht vergessen!)
Um später Typoscript aus der Extension im Backend verfügbar zu machen legen wir ebenfalls in dem Verzeichnis eine sys_template.php mit folgendem Inhalt an. Damit ist sämtlicher TypoScript-Code im Verzeichnis Configuration/TypoScript verfügbar. Das Template wird dann im Backend unter Template > Rootseite wählen > Gesamtes Typoscript bearbeiten > Erweiterte Optionen eingebunden. In dem Typoscript wird bspw. festgelegt, wo die HTML-Templates für die Views liegen.
<?php
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
/**
* Make the extension configuration accessible for TYPO3 Template
*/
ExtensionManagementUtility::addStaticFile('sales', 'Configuration/TypoScript', 'TS template for sales');
PHPDer Content Element Wizard beinhaltet bspw. die Pluginübersicht.

Wenn man das Plugin auch schon direkt im Content Element Wizard auswählen können soll, muss noch folgendes TypoScript ergänzt werden. (EXT:sales/Configuration/TSConfig/Page/ContentElementWizard.tsconfig)
# Configuration for Content Element Wizard
mod.wizards {
newContentElement.wizardItems {
plugins {
elements {
tenders_list {
iconIdentifier = tx-tenders-svgicon
title = LLL:EXT:tenders/Resources/Private/Language/locallang_db.xlf:tx_tenders_tender.pluginlabel
description = LLL:EXT:tenders/Resources/Private/Language/locallang_db.xlf:tx_tenders_tender.plugindescription
tt_content_defValues {
CType = list
list_type = tenders_list
header = LLL:EXT:tenders/Resources/Private/Language/locallang_db.xlf:tx_tenders_tender.pluginlabel
}
}
}
}
}
}
# Add CType Preview
mod.web_layout.tt_content.preview.list.sales_list = EXT:sales/Resources/Private/Templates/PluginPreview/Show.htmlPlaintextIn Zeile 22 wird noch die Ansicht des ContentTypes in der Seite selbst mit einem Template verfeinert. So sieht man schon in der Übersicht, aus welchem Ordner sich die Extension bedient. Das Template EXT:sales/Resources/Private/Templates/PluginPreview/Show.html sieht wie folgt aus.
<html lang="en" xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<h4>Tenders</h4>
<table class="table">
<thead>
<tr>
<th>Config</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Header</strong></td>
<td>{header}</td>
</tr>
<tr>
<td><strong>Storage</strong></td>
<td>{pages}</td>
</tr>
</tbody>
</table>
</html>PHPund hat folgendes Ergebnis

Das Typoscript wird über die Datei EXT:sales/Configuration/page.tsconfig als Typoscript ins Typo3 gepusht.
@import 'EXT:sales/Configuration/TSConfig/Page/ContenElementWizard.tsconfig'PlaintextDas Icon im SVG-Format legt man unter EXT:Resources/Public/Icons ab. (bspw. sales.svg). Unter EXT:Configuration legt man eine Icons.php an, in der man den Icon-Identifier bescheibt.
<?php
declare(strict_types=1);
use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;
return [
// Icon identifier
'tx-sales-svgicon' => [
// Icon provider class
'provider' => SvgIconProvider::class,
// The source SVG for the SvgIconProvider
'source' => 'EXT:sales/Resources/Public/Icons/sales.svg',
]
];
PHPAlle Klassen für das Plugin kommen ins Verzeichnis EXT:sales/Classes. Einstiegspunkt ist der Controller. Der EXT:sales/Classes/Controller/SaleController.php sieht wie folgt aus.
<?php
declare(strict_types=1);
namespace OeKonzept\Sales\Controller;
use InvalidArgumentException;
use OeKonzept\Sales\Domain\Model\Sale;
use OeKonzept\Sales\Domain\Repository\SaleRepository;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
class SaleController extends ActionController
{
/**
* @var \OeKonzept\Sales\Domain\Repository\SaleRepository
*/
protected $saleObjectRepository;
public function injectSaleRepository(SaleRepository $salesObjectRepository)
{
$this->saleObjectRepository = $salesObjectRepository;
}
/**
* Action to list all sales objects
*
* @return ResponseInterface
* @throws InvalidArgumentException
*/
public function listAction()
{
$salesObjects = $this->saleObjectRepository->findSalesWithCampaigns();
$this->view->assign('sales', $salesObjects);
return $this->responseFactory->createResponse()
->withHeader('Content-Type', 'text/html; charset=utf-8')
->withBody($this->streamFactory->createStream($this->view->render()));
}
/**
* Action to show a single sales object
*
* @param Sale $salesObject
* @return ResponseInterface
* @throws InvalidArgumentException
*/
public function showAction(Sale $sale)
{
$this->view->assign('sale', $sale);
return $this->responseFactory->createResponse()
->withHeader('Content-Type', 'text/html; charset=utf-8')
->withBody($this->streamFactory->createStream($this->view->render()));
}
}
PHPDer Controller bekommt seine Daten aus dem Repository. Das Repo ist zuständig für die Datenbeschaffung und der Controller ist damit von der Datenquelle entkoppelt.
Das EXT:sales/Classes/Domain/SaleRepository.php kann recht leer sein, da es die Grundfunktionalitäten vom Extbase Repository erbt.
<?php
namespace OeKonzept\Sales\Domain\Repository;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use TYPO3\CMS\Extbase\Persistence\Repository;
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
class SaleRepository extends Repository
{
public function findSalesWithCampaigns(): QueryResultInterface
{
$query = $this->createQuery();
$query->setOrderings(['bearbeitungsnummer' => 'ASC']);
$sales = $query->execute();
return $sales;
}
}
PHPDamit Extbase die einzelnen Datensätze in ein Model packen kann, erstellt man ein Domain Model dafür. (EXT:sales/Classes/Domain/Model/Sale.php)
<?php
namespace OeKonzept\Sales\Domain\Model;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
class Sale extends AbstractEntity
{
protected string $bearbeitungsnummer = '';
protected string $titel = '';
protected float $preis = 0.0;
protected string $preisart = '';
protected string $beschreibung = '';
protected \TYPO3\CMS\Extbase\Domain\Model\FileReference $bilder;
protected \TYPO3\CMS\Extbase\Domain\Model\FileReference $uploads;
protected int $tx_sales_campaign_uid = 0;
/**
* Get the value of bearbeitungsnummer
*/
public function getBearbeitungsnummer(): string
{
return $this->bearbeitungsnummer;
}
/**
* Set the value of bearbeitungsnummer
*/
public function setBearbeitungsnummer(string $bearbeitungsnummer): self
{
$this->bearbeitungsnummer = $bearbeitungsnummer;
return $this;
}
/**
* Get the value of titel
*/
public function getTitel(): string
{
return $this->titel;
}
/**
* Set the value of titel
*/
public function setTitel(string $titel): self
{
$this->titel = $titel;
return $this;
}
/**
* Get the value of preis
*/
public function getPreis(): float
{
return $this->preis;
}
/**
* Set the value of preis
*/
public function setPreis(float $preis): self
{
$this->preis = $preis;
return $this;
}
/**
* Get the value of preisart
*/
public function getPreisart(): string
{
return $this->preisart;
}
/**
* Set the value of preisart
*/
public function setPreisart(string $preisart): self
{
$this->preisart = $preisart;
return $this;
}
/**
* Get the value of beschreibung
*/
public function getBeschreibung(): string
{
return $this->beschreibung;
}
/**
* Set the value of beschreibung
*/
public function setBeschreibung(string $beschreibung): self
{
$this->beschreibung = $beschreibung;
return $this;
}
/**
* Get the value of bilder
*/
public function getBilder(): \TYPO3\CMS\Extbase\Domain\Model\FileReference
{
return $this->bilder;
}
/**
* Set the value of bilder
*/
public function setBilder(\TYPO3\CMS\Extbase\Domain\Model\FileReference $bilder): self
{
$this->bilder = $bilder;
return $this;
}
/**
* Get the value of uploads
*/
public function getUploads(): \TYPO3\CMS\Extbase\Domain\Model\FileReference
{
return $this->uploads;
}
/**
* Set the value of uploads
*/
public function setUploads(\TYPO3\CMS\Extbase\Domain\Model\FileReference $uploads): self
{
$this->uploads = $uploads;
return $this;
}
/**
* Get the value of tx_sales_campaign_uid
*/
public function getTxSalesCampaignUid(): int
{
return $this->tx_sales_campaign_uid;
}
/**
* Set the value of tx_sales_campaign_uid
*/
public function setTxSalesCampaignUid(int $tx_sales_campaign_uid): self
{
$this->tx_sales_campaign_uid = $tx_sales_campaign_uid;
return $this;
}
}
PHPExtbase wird mit der entsprechenden Tabelle, welche die Daten für das Model enthält in EXT:sales/Configuration/Extbase/Persistance/Classes.php verbunden.
<?php
/**
* Mapping of classes to tables
*/
declare(strict_types=1);
return [
\OeKonzept\Sales\Domain\Model\Sale::class => [
'tableName' => 'tx_sales_object',
]
];
PHPDer Controller für das Plugin muss konfiguriert werden in der EXT:sales/ext_localconf.php.
<?php
use OeKonzept\Sales\Controller\SaleController;
use TYPO3\CMS\Extbase\Utility\ExtensionUtility;
ExtensionUtility::configurePlugin(
'Sales',
'list',
[
SaleController::class => 'list, show'
]
);
PHPFür die Auflistung der einzelnen Datensätze bspw. EXT:sales/Resources/Private/Templates/Sale/List.html
<ul>
<f:for each="{sales}" as="sale">
<li>
<f:link.action action="show" arguments="{sale: sale}" class="btn btn-link">{sale.titel}
</f:link.action>
</li>
</f:for>
</ul>PHPMit folgendem Befehl bekommt man sein System ggf. wieder zum Laufen, wenn bspw. Berechtigungsprobleme das Lesen von Dateien verhindern und damit das komplette System crashen.
ddev debug test
Datei .ddev/php/tz.ini anlegen und folgendes eintragen date.timezone = Europe/Berlin
Dann ddev restart
Im Setup des Templates der Seite angeben
config.contentObjectExceptionHandler = 0