unionofrad / li3_behaviors
li₃ PHP 框架的模型行为
Requires
- php: ^5.4 || ^7
- composer/installers: ^1
- unionofrad/lithium: ^1.2
This package is auto-updated.
Last update: 2024-09-11 02:01:18 UTC
README
这个库提供了实现模型行为的基类。模型行为提供了一种简单的方式来扩展模型。这种模式允许将常见逻辑封装在行为中,以保持模型轻量级,并由其自身的业务逻辑组成。
安装
首选的安装方法是使用 composer。您可以通过以下方式将库作为依赖项添加:
composer require unionofrad/li3_behaviors
li₃ 插件必须在您的应用程序引导阶段注册,因为它们使用不同的(更快)自动加载器。
Libraries::add('li3_behaviors')
官方手册提供了有关如何注册插件以及使用替代安装方法(例如,通过 Git)的更多信息。
使用
管理和加载行为
首先,要在模型中添加使用行为的能力,请在您的模型中使用行为特性。之后,在模型类的 $_actsAs
属性中定义您计划使用的所有行为。
// ... class Posts extends \lithium\data\Model { use li3_behaviors\data\model\Behaviors; protected $_actsAs = [ 'Sluggable' => ['field' => 'slug', 'label' => 'title'] ]; // ...
Behaviors
特性还在模型中提供了一些静态方法,允许按以下方式管理行为。
// Bind the sluggable behavior with configuration. Posts::bindBehavior('Sluggable', ['field' => 'slug', 'label' => 'title']); // Accessing configuration. Posts::behavior('Sluggable')->config(); Posts::behavior('Sluggable')->config('field'); // Updating configuration. Posts::behavior('Sluggable')->config('field', 'alt'); // Unbinding it again. Posts::unbindBehavior('Sluggable');
创建行为
现在,我们已经能够加载和管理行为,可以创建自己的行为,它必须扩展 Behavior
基类。在以下示例中,我们在 extensions/data/behavior/Sluggable.php
中创建了一个 Sluggable
行为。
namespace app\extensions\data\behavior; use lithium\util\Inflector; class Sluggable extends \li3_behaviors\data\model\Behavior { protected static $_defaults = [ 'field' => 'slug', 'label' => 'title' ]; protected static function _filters($model, $behavior) { Filters::apply($model, 'save', function($params, $next) use ($behavior) { $params['data'][$behavior->config('field')] = static::_generate( $params['data'][$behavior->config('label')] ); return $next($params); }); } protected static function _generate($value) { return strtolower(Inflector::slug($value)); } }
行为配置
可以通过行为内的 config()
访问每个行为的配置。默认情况下,将自动使用用户提供的配置(来自模型类的 $_actsAs
属性)和行为提供的默认值(作为 $_defaults
)设置行为的默认配置。
默认值将使用简单的数组添加($config += $defaults
)与提供的配置合并。如果您想更改配置合并的方式,请继续阅读。
提供自定义配置逻辑
行为通常对配置有不同的要求。在某些情况下,只需要合并一个一维数组,在其他情况下,必须合并或以自定义方式归一化嵌套的多维数组。
这就是为什么可以很容易地由自己(实现者)控制默认值与提供的配置的合并 - 默认情况下,我们执行简单的单维合并,将默认值和配置相加。要控制配置合并,请覆盖基类中的 _config()
方法。
在以下示例中,我们将合并行为默认值时归一化某些配置选项。
// ... class Serializable extends \li3_behaviors\data\model\Behavior { protected static $_defaults = [ 'fields' => [] ]; protected static function _config($model, $behavior, $config, $defaults) { $config += $defaults; $config['fields'] = Set::normalize($config['fields']); foreach ($config['fields'] as $field => &$pass) { if (!$pass) { $pass = 'json'; } } return $config; } // ...
_config()
方法接收配置和 $_defaults
中定义的默认值作为第三个和第四个参数。该方法必须最终返回应用于行为实例的配置。
将静态方法公开给模型
行为中存在的任何公共静态方法都会自动公开在模型上。这允许轻松地向模型添加方法。每个公开的静态方法都将其当前模型类名称作为第一个参数,将行为实例作为第二个参数。
如果您需要查询模型以获取结果或想从行为中检索配置,这将很有用。
以下示例显示了如何将令牌生成方法公开给模型。
// ... class TokenGenerator extends \li3_behaviors\data\model\Behavior { protected static $_defaults = [ 'short' => false ]; // Generates a random token either short (8 chars) or long (16 chars) and // returns it. Default expiration is one year. public static function token($model, $behavior) { $token = substr(md5(Random::generate(32)), 0, $behavior->config('short') ? 8 : 16); $expires = date('Y-m-d H:i:s', strtotime('+1 year')); return compact('token', 'expires'); } // ...
将实例方法公开给模型
类似于公开静态方法,实例方法也可以轻松公开给模型。行为中实现的所有具体方法都将被公开。除了$entity
参数外,每个行为方法还将接收模型的名称和行为实例作为第二个参数,即用于访问配置。
// ... class Publishable extends \li3_behaviors\data\model\Behavior { protected static $_defaults = [ 'field' => 'is_published' ]; public function publish($model, $behavior, $entity) { $field = $behavior->config('field'); $entity->{$field} = true; } // ...
动态添加模型实例方法
有时您需要动态地向模型实例添加方法。例如,当行为字段的名称是用户可配置的,并需要将其作为方法添加到实体上时。
这可以通过覆盖_methods()
方法并返回一个按模型实例上的别名键控的方法数组来实现。
// ... class Taggable extends \li3_behaviors\data\model\Behavior { // ... protected static function _methods($model, $behavior) { return [ $behavior->config('field') => function() { /* ... */ } ] } // ...
上述示例行为将使模型返回的每个实体都启用以下方法。
Posts::bindBehavior('Taggable', ['field' => 'taxonomy']); $item = Posts::create(); $item->taxonomy();
将过滤器附加到模型上
要修改现有的模型方法,应使用过滤器。如果您的行为需要使用过滤器,一个好的地方是在行为体的_filters()
方法中附加它们。覆盖它以在初始化阶段将过滤器附加到模型。
// ... class Timestamp extends \li3_behaviors\data\model\Behavior { // ... protected static function _filters($model, $behavior) { Filters::apply($model, 'save', function($params, $next) use ($behavior) { $params['data'] = static::_timestamp($behavior, $params['entity'], $params['data']); return $next($params); }); } protected static function _timestamp($behavior, $entity, $data) { // ... } // ...
将查找器附加到模型上
要向模型的查找方法添加查找器,应使用查找器。如果您的行为需要使用查找器,一个好的地方是在行为体的_finders()
方法中附加它们。覆盖它以在初始化阶段将查找器添加到模型。
// ... class Taggable extends \li3_behaviors\data\model\Behavior { // ... protected static function _finders($model, $behavior) { $model::finder('tag', function($params, $next) use ($behavior) { // ... return $next($params); }); } // ...
版权 & 许可
版权 2010 Union of RAD。保留所有权利。本库根据BSD 3-Clause License分发。完整的许可文本可以在LICENSE.txt文件中找到。
前版实现致谢
- David Persson,https://github.com/davidpersson/li3_behaviors
- Nate Abele,https://github.com/nateabele/li3_behaviors
- Simon Jaillet,https://github.com/jails/li3_behaviors