jeyroik / extas-foundation
Extas 基础包
Requires
- ext-json: *
- jeyroik/extas-base: 2.*
- jeyroik/extas-exceptions: 0.*
- jeyroik/extas-id: 0.*
- league/container: 4.*
- symfony/console: 6.*
- symfony/finder: 6.*
Requires (Dev)
- jeyroik/extas-snuffbox: 1.*
- phpunit/phpunit: ^9
- vlucas/phpdotenv: ^5.5
- dev-master
- v6.x-dev
- 6.22.1
- 6.22.0
- 6.21.3
- 6.21.2
- 6.21.1
- 6.21.0
- 6.20.0
- 6.19.0
- 6.18.4
- 6.18.3
- 6.18.2
- 6.18.1
- 6.18.0
- 6.17.0
- 6.16.1
- 6.16.0
- 6.15.1
- 6.15.0
- 6.14.0
- 6.13.0
- 6.12.0
- 6.11.2
- 6.11.1
- 6.11.0
- 6.10.0
- 6.9.1
- 6.9.0
- 6.8.1
- 6.8.0
- 6.7.0
- 6.6.0
- 6.5.3
- 6.5.2
- 6.5.1
- 6.5.0
- 6.4.1
- 6.4.0
- 6.3.0
- 6.2.0
- 6.1.2
- 6.1.1
- 6.1.0
- 6.0.0
- v5.x-dev
- 5.15.0
- 5.14.1
- 5.14.0
- 5.13.0
- 5.12.2
- 5.12.1
- 5.12.0
- 5.11.0
- 5.10.0
- 5.9.0
- 5.8.1
- 5.8.0
- 5.7.2
- 5.7.1
- 5.7.0
- 5.6.0
- 5.5.0
- 5.4.0
- 5.3.0
- 5.2.0
- 5.1.0
- 5.0.1
- 5.0.0
- 4.1.0
- 4.0.0
- 3.1.0
- 2.1.0
- 2.0.0
- 1.2.0
- 1.0.0
- 0.7.1
- 0.7.0
- 0.6.2
- 0.5.1
- dev-development
This package is auto-updated.
Last update: 2024-09-16 15:54:00 UTC
README
描述
该包包含 Extas 的基本实体
extas\components\Item基础对象,允许使用开箱即用的插件和扩展(见下文)extas\components\plugins\Plugin插件。允许实现插件(详细信息见下文)。extas\components\extensions\Extension扩展。允许为从Item继承的类实现扩展(装饰器)。
要求
- PHP 7.4+
- 任何存储(默认使用 JSON 文件进行测试)。
安装包
# composer require jeyroik/extas-foundation:6.*
安装 Extas 兼容的应用程序
# vendor/bin/extas install -t "repo/template/path" -s "repo/classes/save/path"
对于实体,有一个 extas\\interfaces\\stages\\IStageBeforeInstallEntity 阶段,通过连接到该阶段可以对实体数据进行额外操作。
应用程序的实体配置先于库的实体配置。
# vendor/bin/extas-extra e
有关 extra 命令的详细信息,请参阅下文。
安装其他实体
要安装其他实体,可以使用 extra 命令。通过插件,可以连接到该命令,并通过统一接口安装任何实体,并执行所需的各种操作。
要查看可用选项的列表,请使用命令的帮助
# vendor/bin/extas extra -h
应用程序配置
- 为了配置您的应用程序,需要创建两个文件
extas.app.storage.json用于配置存储、插件和扩展;extas.app.json用于配置实体。- 最小配置可以在
extas.app.storage.dist.json中找到,以及在下文的当前文档中。extas.app.dist.json,以及在下文的当前文档中。- 如果开发库,则必须将库的配置存储在
extas.storage.json- 存储配置、插件和扩展。extas.json- 实体配置。extas.storage.dist.json,以及在下文的当前文档中。- 最小配置可以在
extas.app.storage.dist.json中找到,以及在下文的当前文档中。extas.dist.json,以及在下文的当前文档中。extas.dist.json,以及在下文的当前文档中。
运行测试
# composer test
使用
Item
应该将基本实体用作您的实体(模型等)的父类。
class My extends extas\components\Item
在这种情况下,您将立即获得
- 动态属性支持:
$my = new My(); $my->some = 'thing'; - 数组接口支持
$my = new My(); $my['fieldName'] = 5; $val = $my['fieldName']; echo $val;// 5 isset($my['fieldName']); // true unset($my['fieldName']); isset($my['fieldName']); // false
- 迭代器支持:
foreach($my as $field => $value) - 装饰器支持:
$my->notExistingMethod($arg1, $arg2) - 快速访问存储支持:
$my->myTable()->one(...) - 插件(事件)支持:在
My类的方法内部- 创建实体
<实体>.created,在将新实体实例保存到存储时触发; - 实体初始化
<实体>.init,在初始化实体对象时触发; - 实体对象删除
<实体>.after,在删除实体对象时触发 - 分别转换为数组、字符串和整数
<实体>.to.array、<实体>.to.string、<实体>.to.int
- 创建实体
- 支持一系列辅助方法(每个方法都为插件提供相应的事件)类型
- __toArray()
- __toJson()
- __toInt()
- __equal(IItem $other) - 与其他实体比较。
- __has('attr1', 'attr2', ...) - 检查是否存在必要的属性。
- __select('attr1', 'attr2', ...) - 获取具有有限字段集的实体。
- 支持为插件创建新事件
foreach($this->getPluginsByStage('event.name') as $plugin) { $plugin($arg1, $arg2); }
以下,在审查每个基本实体之后,将展示一个使用所有实体(整体和单独)的工作示例。
插件
应将插件用作您插件的父类。
class MyPlugin extends extas\components\plugins\Plugin {}
要实现插件,您需要重载 __invoke() 方法。方法参数取决于具体阶段(事件)。
下面是插件实现的示例。
预安装插件
在应用程序的 extas.app.storage.json 和库的 extas.storage.json 中。
{
"plugins": [
{
"class": "class\\Name",
"stage": "stage.name",
"priority": 10
}
]
}
priority - 优先级越高,插件越早(相对于同一阶段的其他插件)执行。此参数是可选的。
扩展
应将扩展用作您扩展(装饰器)的父类。扩展允许动态且透明地向实体添加方法,而不修改其代码。
class MyExtension extends extas\components\Extension implements IMyExtension{}
预安装扩展
在应用程序的 extas.app.storage.json 和库的 extas.storage.json 中。
{
"extensions": [
{
"class": "extension\\Class",
"interface": "extension\\Interface",
"subject": ["subject.name.1", "subject.name.2", "*"],
"methods": ["method1", "method2"]
}
]
}
单独和一起使用每个实体的示例
Item
namespace my\extas; use extas\components\Item; class My extends Item { public function getName() { return $this->config['name'] ?? ''; } public function setName($name) { $this->name = $name; return $this; } protected function getSubjectForExtension(): string { return 'my'; } } $my = new my\extas\My(['name' => 'on init']); echo $my['name']; // 'on init' echo $my->getName(); // 'on init' echo $my->name; // 'on init' $my['description'] = 'Using Item example'; foreach($my as $field => $value) { echo $field . ' = ' . $value; } /** * Will output: * name = on init * description = Using Item example */
插件
namespace my\extas; use extas\components\Item; class My extends Item { public function getName() { $name = $this->config['name'] ?? ''; foreach($this->getPluginsByStage('my.name.get') as $plugin) { $plugin($name); } return $name; } public function setName($name) { $this->config['name'] = $name; return $this; } protected function getSubjectForExtension(): string { return 'my'; } } use extas\components\Plugin; class PluginEmptyName extends Plugin { public function __invoke(&$name) { $name = $name ?: 'Missed "name"'; } } // extas.storage.json/extas.app.storage.json { "plugins": [ { "class": "my\\extas\\PluginEmptyName", "stage": "my.name.get" } ] } // somewhere in a code $my = new My(); echo $my->getName(); // 'Missed "name"'
注意!为了使上述示例生效,插件必须安装到系统中。详细信息请参阅 安装 部分。
扩展
namespace my\extas; use extas\components\Item; class My extends Item { public function getName() { $name = $this->config['name'] ?? ''; foreach($this->getPluginsByStage('my.name.get') as $plugin) { $plugin($name); } return $name; } public function setName($name) { $this->config['name'] = $name; return $this; } protected function getSubjectForExtension(): string { return 'my'; } } /** * Для расширений рекомендуется всегда подготавливать интерфейсы. * Это помогает при разработке (подсказки) и позволяет удобнее контролировать расширения. */ interface IGetMutatedName { /** * @return string */ public function getMutatedName(): string; } use extas\components\Extension; class MyGetMutatedName extends Extension implements IGetMutatedName { public string $subject = 'my'; /** * Последним аргументом любого метода, который является расширением, * передаётся экземпляр сущности, которая расширяется * * @param null|My $my * * @return string */ public function getMutatedName(My $my = null) { $name = $my->getName(); return str_replace('.', '\\', $name); } } // extas.storage.json/extas.app.storage.json { "extensions": [ { "class": "my\\extas\\MyGetMutatedName", "interface": "my\\extas\\IGetMutatedName", "subject": ["my"], "methods": ["getMutatedName"] } ] } // somewhere in a code $my = new My(['name' => 'extas.extensions.extension.example']); echo $my->getMutatedName(); // extas\\extensions\\extension\\example
注意!为了使上述示例生效,扩展必须安装到系统中。详细信息请参阅 安装 部分。
extas.app.storage.json
{
"name": "vendor/package",
"drivers": [
{
"driver": "\\driver\\Class",
"options": {
"dsn": "{username}:{userpassword}@{host}:{port}/{db} | {path/to/db}",
"username": "",
"password": "",
"host": "",
"port": "",
"db": ""
},
"tables": ["t1", ...]
}
],
"tables": {
"some_entities": {
"item_class": "",
"pk": "",
"aliases": ["alias1", ...],
"hooks": {
"create-before": true,
"update-before": true,
"update-after": true,
...
},
"code": {
"create-before": "echo 'any code you want'; \\extas\\components\\repositories\\RepoItem::throwIfExist($this, $item, ['name'])",
...
}
},
...
},
"plugins": [
{
...
},
...
],
"extensions": [
{
...
},
...
],
"envs": [
"name1": "description"
]
}
extas.app.json
应用程序的实体配置先于库的实体配置。
{
"some_entities": [
{
...
},
...
]
}
extas.storage.json
注意:不要在此配置中将设置驱动器的部分放在这里 - 它将被忽略。驱动器在 extas.app.storage.json 中配置。
{
"name": "vendor/package",
"tables": {
"some_entities": {
"item_class": "",
"pk": "",
"aliases": ["alias1", ...],
"hooks": {
"create-before": true,
"update-before": true,
"update-after": true,
...
},
"code": {
"create-before": "echo 'any code you want';",
...
}
},
...
},
"plugins": [
{
...
},
...
],
"extensions": [
{
...
},
...
],
"envs": {
"name1": "description 1"
}
}
extas.json
{
"some_entities": [
{
...
},
...
]
}
ENV
要了解需要哪些环境变量,请执行 env 命令。
# vendor/bin/extas env
要将自己的环境变量添加到该列表中,请将 extas.app.storage.json(对于库在 extas.storage.json)配置中的 envs 部分添加,并按上述配置示例描述您的变量。