orange-hive / simplyment
为TYPO3开发者简化开发
Requires
- php: ^8.0
- typo3/cms-core: ^12
Suggests
- typo3/cms-fluid-styled-content: Required for custom content elements
README
本扩展的目标是减少在配置、设置和跳转于TYPO3扩展代码以执行常见任务上所花费的时间。
通过约定存储位置(例如后端布局)或使用类和属性的PHP属性来简化扩展的开发。
将更多时间集中在有趣的方面,如编写逻辑,并加快开发速度!
要求
- PHP 8.0或更高版本
- TYPO3 11.5
安装
- 使用Composer安装扩展 - 依赖项名称:orange-hive/simplyment
配置
在加载用于定义页面配置typoscript的静态typoscript之前,将静态“Simplyment”包含到您的模板中
如果您想使用Simplyment的后端布局和前端模板加载。这已经定义了页面=PAGE,并使用了10 = FLUIDTEMPLATE。
如果您想自己定义页面对象,可以使用基于后端布局名称的模板自动加载
使用以下代码为templateName
templateName < simplyment.page.resolveTemplateName
将以下代码添加到您的扩展中 - 就这么简单!
- 文件:Configuration/Services.yaml
services: MyVendorName\MyExtensionKey: tags: - name: simplyment
或者,您可以选择跳过在Configuration/Services.yaml中的注册,并手动注册您的扩展以用于Simplyment
- 文件:ext_localconf.php
\OrangeHive\Simplyment\Loader::extLocalconf( vendorName: 'MyVendorName', extensionName: 'my_extension_key' );
- 文件:ext_tables.php
\OrangeHive\Simplyment\Loader::extTables( vendorName: 'MyVendorName', extensionName: 'my_extension_key' );
作为第三个参数,您可以将loaders作为包含您想要使用的加载器的数组添加。如果没有定义加载器,则将使用所有加载器。
使用方法
后端布局
加载器:BackendLayoutLoader
您可以通过创建扩展名为.ts、.tsconfig、.typoscript或.txt的TypoScript文件来创建后端布局定义
在您的扩展目录EXT:<MY_EXTENSION>\Resources\Private\BackendLayouts中。
文件名必须写成lower_snake_case。
在文件中使用以下结构
{
title = My title
description = My template description
icon = EXT:my_extension/Resources/Public/Images/BackendLayouts/default.png
config {
backend_layout {
colCount = 1
rowCount = 1
rows {
1 {
columns {
1 {
name = LLL:EXT:my_extension/Resources/Private/Language/locallang_be.xlf:backend_layout.column.normal
colPos = 0
}
}
}
}
}
}
}
对于title和description属性,您可以使用LLL-notation来使用本地化翻译。
前端模板由您的TemplatesRootPath目录自动确定。
您的模板文件名必须与后端布局文件名相同,但使用UpperCamelCase代替lower_snake_case!
插件
加载器:PluginLoader
您可以直接在ActionController上使用PHP属性Plugin来注册新的插件。您可以通过在动作方法上添加PHP属性PluginAction来添加插件操作。
向您的插件添加FlexForm
您可以使用在Plugin PHP属性中的flexFormPath属性轻松地将FlexForm添加到插件中。此属性的值必须是一个以EXT:开头的字符串,并定义了FlexForm XML文件的路径。如果没有定义FlexForm,Simplyment会尝试在位置EXT:my_extension/Configuration/FlexForms/MyPluginName.xml中找到FlexForm文件,并自动添加此文件。
要使用此功能,请将以下代码添加到您的扩展中的TCA/Overrides/tt_content.php文件
\OrangeHive\Simplyment\Loader::tcaTtContentOverrides('MyVendorName', 'my_extension_key');
数据库模型
加载器:DatabaseModelLoader
使用PHP属性DatabaseTable注册新的数据库模型。应将PHP属性DatabaseField定义的字段类型应用于模型应持久化到数据库表的属性。
要生成TCA,请将PHP属性TcaField添加到您的属性中。
您还可以将PHP属性Tca添加到您的类中,以定义以下选项
- 图标:包含模型自定义图标路径的字符串,如果没有提供,则使用Simplyment扩展图标
- allowOnStandardPage:布尔值 - 允许在标准页面上添加表条目,而不仅仅是文件夹中,默认:false
- config:数组 - 全局TCA配置,可以覆盖此模型的TCA值
对于新数据库模型的TCA配置,如果不存在,则在清除缓存时由Simplyment自动在 配置/TCA/ 中生成TCA文件,包含以下内容
<?php $base = \OrangeHive\Simplyment\Utility\ModelTcaUtility::getTca(\MyVendor\MyExtension\Domain\Model\MyModel::class); $custom = []; \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($base, $custom); return $base;
注意
\MyVendor\MyExtension\Domain\Model\MyModel 将是模型的完全限定类名。
在数组 $custom 中,您可以覆盖自动生成的TCA配置。
扩展现有表
可以通过在DatabaseTable属性中添加 tableName 属性来扩展现有表。
可以在表中定义为属性(无需任何PHP属性)的现有字段。自定义字段必须接收 DatabaseField 和 TcaField PHP属性。示例
<?php namespace MyVendor\MyExtension\Domain\Model; use OrangeHive\Simplyment\Attributes\DatabaseField; use OrangeHive\Simplyment\Attributes\DatabaseTable; use OrangeHive\Simplyment\Attributes\TcaField; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; #[DatabaseTable( tableName: 'pages' // extending table 'pages' )] class Page extends AbstractEntity { protected string $title = ''; // already existent field title #[DatabaseField(type: 'text')] #[TcaField] protected string $txMyField; // custom field /** * @return string */ public function getTitle(): string { return $this->title; } /** * @return string */ public function getTxMyField(): string { return $this->txMyField; } }
除了 配置/TCA/ 中的文件外,还会在 配置/TCA/Overrides/ 中创建一个以tableName为文件名的文件。
如果不存在,则在清除缓存时由Simplyment自动生成文件的内容,包含以下内容
<?php use OrangeHive\Simplyment\Utility\ModelTcaUtility; $customColumnOverrides = []; ModelTcaUtility::addColumnTcaOverrides( fqcn: (\MyVendor\MyExtension\Domain\Model\MyModel::class, tableName: 'givenTableName', columnOverrides: $customColumnOverrides ); ModelTcaUtility::addColumnsToAllTcaTypes( fqcn: (\MyVendor\MyExtension\Domain\Model\MyModel::class, tableName: 'givenTableName' );
注意
\MyVendor\MyExtension\Domain\Model\MyModel 将是模型的完全限定类名。
givenTableName 将是DatabaseTable属性中定义的tableName。您在模型中定义的所有自定义字段将被添加到所有TCA类型中。在 ModelTcaUtility::addColumnsToAllTcaTypes 方法中,您可以使用 fieldsOverride 参数限制要添加的字段(或通过提供自定义数组中的字段来更改顺序)来限制要添加的字段。此外,您可以使用包含以逗号分隔的值的字符串的 typeList 参数来定义字段应仅添加的类型。还可以使用 position 属性定义插入的位置。
逻辑基于 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes (https://docs.typo3.org/m/typo3/reference-coreapi/11.5/en-us/ExtensionArchitecture/HowTo/ExtendingTca/Examples/Index.html)。
与ObjectStorage的关系
对于ObjectStorage关系,如通常在属性上面的文档块中定义ObjectStorage的PHP注解一样编写
/** * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\MyVendor\MyExtension\Domain\Model\MySubModel> */
您可以定义TCA,或者使用具有 type 和 targetClass 参数的 TcaField 属性。
这将通过反射扫描定义的目标类,并搜索具有您模型类型的属性,从而从您引用的子模型引用该模型。此属性用作TCA中的外键字段。默认情况下,foreign_sortby 设置为 sorting。
#[DatabaseField(sql: 'int')] #[TcaField( label: 'Sub models', type: TcaFieldTypeEnum::INLINE, targetClass: TestSubModel::class )] protected ObjectStorage $subModels;
有预定义的类型用于引用FAL文件(TcaFieldTypeEnum::FILE) 、图像(TcaFieldTypeEnum::FILE_IMAGE) 或媒体(TcaFieldTypeEnum::FILE_MEDIA)。
仅通过FAL引用图像的示例
/** * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference> */ #[DatabaseField(sql: 'int')] #[TcaField( label: 'My images', type: TcaFieldTypeEnum::FILE_IMAGE )] protected ObjectStorage $images;
自定义内容元素
加载器:ContentElementLoader
必须在您的扩展中的 Classes\Domain\Model\Content 目录中创建自定义内容元素。对于每个自定义内容元素,创建一个新的PHP类并使用PHP属性 ContentElement,并设置属性 name。
类必须扩展 TYPO3\CMS\Extbase\DomainObject\AbstractEntity。
使用类中的属性定义内容元素字段。您可以重用现有字段。
对于自定义字段,将其作为属性添加,并添加PHP属性 DatabaseField(用于在SQL中生成字段)和 TcaField(用于定义字段的配置)。
对于现有字段,可以通过使用PHP属性 TcaField 来覆盖TCA配置。
如果 TcaField 中没有定义标签,并且属性具有 DatabaseField PHP属性,则使用翻译密钥 LLL:EXT:<MY_EXTENSION>/Resources/Private/Language/locallang.xlf:tt_content.<field_name>。
重要
为所有属性添加获取器方法,以便在前端模板中访问这些属性!
为了加载自定义内容元素的TCA配置,请将以下代码添加到 <MY_EXTENSION>\Configuration\TCA\Overrides\tt_content.php
\OrangeHive\Simplyment\Loader::tcaTtContentOverrides('MyVendorName', 'my_extension_key');
注意
如果该文件不存在,则由Simplyment在清除缓存时自动生成。
此外,将以下代码添加到 <MY_EXTENSION>\Configuration\Extbase\Persistence\Classes.php 以自动将自定义内容元素映射到tt_content表
$mapping = \OrangeHive\Simplyment\Loader::classes('##VENDOR_NAME##', '##EXTENSION_KEY##'); $custom = []; return array_merge($mapping, $custom);
注意
如果该文件不存在,则由Simplyment在清除缓存时自动生成。
自定义内容元素PHP类的示例
<?php namespace MyVendor\MyExtension\Domain\Model\Content; use OrangeHive\Simplyment\Attributes\ContentElement; use OrangeHive\Simplyment\Attributes\DatabaseField; use OrangeHive\Simplyment\Attributes\TcaField; use OrangeHive\Simplyment\Enumeration\TcaFieldTypeEnum; use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; #[ContentElement( name: 'Teaser' )] class Teaser extends AbstractEntity { protected string $header = ''; // use already existent header field #[TcaField( type: TcaFieldTypeEnum::TEXT, config: [ 'enableRichtext' => true, ] )] protected string $bodytext = ''; // use already existent bodytext field and define it as type='text' with richtext enabled #[TcaField( type: TcaFieldTypeEnum::TEXT, config: [ 'enableRichtext' => true, ] )] #[DatabaseField(type: 'mediumtext')] protected string $txAdditionalText = ''; // create custom field tx_additional_text and define it as type='text' with richtext enabled /** * @return string */ public function getHeader(): string { return $this->header; } /** * @return string */ public function getBodytext(): string { return $this->bodytext; } /** * @return string */ public function getTxAdditionalText(): string { return $this->txAdditionalText; } }
自定义内容元素的模板文件位于 EXT:<MY_EXTENSION>/Resources/Privat/Templates/Content/。前端模板的名称与PHP类的名称相同,后端模板的名称为PHP类名称加上后缀 Backend。
如果文件不存在,则由Simplyment在清除缓存时自动创建带有虚拟内容的这两个文件。
将FlexForm添加到您的自定义内容元素中
您可以使用 ContentElement PHP属性中的 flexFormPath 属性轻松地将FlexForms添加到自定义内容元素中。此属性的值必须是一个以 EXT: 开头的字符串,并定义到您的FlexForm XML文件的路径。如果没有定义FlexForm,Simplyment将尝试在 EXT:my_extension/Configuration/FlexForms/Content/MyContentElementName.xml 位置查找FlexForm文件,并自动添加。
FlexForm将自动添加到您的列的末尾。您可以通过定义以下方式在您的Model中指定位置
#[TcaField( type: TcaFieldTypeEnum::FLEX )] protected string $piFlexform = '';
要获取Fluid模板中的FlexForm内容,请在您的内容元素模型中添加以下代码的getter
public function getPiFlexform(): array { return \OrangeHive\Simplyment\Utility\FlexFormUtility::xml2array((string)$this->piFlexform); }
要使用此功能,请将以下代码添加到您的扩展中的TCA/Overrides/tt_content.php文件
\OrangeHive\Simplyment\Loader::tcaTtContentOverrides('MyVendorName', 'my_extension_key');
钩子
加载器:HookLoader
可以通过使用PHP属性 Hook 来注册钩子。定义您的钩子类或方法应该绑定的 identifier 和 key。
示例
namespace OrangeHive\Simplyment\Hook; use OrangeHive\Simplyment\Attributes\Hook; use TYPO3\CMS\Backend\View\BackendLayout\DataProviderInterface; #[Hook(identifier: 'TYPO3_CONF_VARS/SC_OPTIONS/BackendLayoutDataProvider', key: 'simplyment')] class BackendLayoutDataProvider implements DataProviderInterface { // not relevant }
将在您的扩展的 ext_localconf.php 中产生以下原生钩子
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider']['simplyment'] = 'OrangeHive\Simplyment\Hook\BackendLayoutDataProvider';
注意
如果未设置 key 属性,则将使用当前时间戳作为键。