barcodex / kasha-model
为 Kasha PHP 框架提供 DB 模型支持
Requires
- php: >=5.3.2
- barcodex/kasha-caching: *
- barcodex/templar: *
- phpunit/phpunit: 4.5.*
This package is not auto-updated.
Last update: 2024-09-28 17:54:27 UTC
README
模型库旨在用于基于 Kasha 框架构建的 Web 应用程序。
它是一个简单的数据库抽象层,不是为了与 ORM 库竞争。
然而,它极大地简化了使用业务对象(这些对象是扩展 Kasha\Model\Model 的类的实例)与数据库表一起工作。
安装
使用 Composer 安装模型库,通过将要求添加到项目的 composer.json 中
{ "require": { "barcodex/kasha-model": "*" } }
或从命令行要求它
composer require barcodex/kasha-model:*
## API
此基类(Kasha\Model\Model)包含大量通用代码,适用于任何数据库表包装器,例如 CRUD 操作、反射、字符串字段的国际化以及后处理触发器的占位符。
公共方法(不完整列表)
还有一些用于在扩展 Kasha\Model\Model 的业务类中非常有用的方法的占位符
## 约定
Kasha 假设数据库表结构遵循某些规则
- 表中至少有一个 'id' 字段。即使表是映射表,也始终添加 'id' 字段
- 有一个名为 'created' 的字段来标记创建此行的时间
- 有名为 'updated' 和 'editor' 的字段来标记最后更新时间和进行此编辑的用户 ID
内部
Kasha 整个框架都青睐 PHP 的标准关联数组 - 如果你曾经尝试在 mysql 结果上使用 fetch_assoc 方法,你就知道这样一个数组如何表示表中的一行。
模型子类建立在内部称为 'data' 的数组之上。要从任何时刻获取此数组,只需调用 getData() 方法。
当然,模型是一个业务对象,这意味着可以在数据数组之上构建任何逻辑 - 最值得注意的是添加新字段。
然而,我们强烈建议在 getExtendedData() 方法(默认情况下仅包装 getData())内扩展原始数据数组。
$bookModel = new Book(); // use load() to populate model object with data, it's chainable $data = $book->load($id)->getData(); // data that corresponds to table structure $extendedData = $book->getExtendedData(); // same data plus additional fields
使用模型子类的一个最大优点实际上是后处理钩子功能。你可以在 onDelete()、onInsert() 和 onUpdate() 方法中实现你的业务逻辑(级联删除/更新、刷新统计数据、清除缓存值、排队消息、发送邮件等 - 你可以命名它),并且你可以根据更改的字段或甚至这些字段的前期值来做这件事。
例如,你可以编写特定的代码,仅在字段 'status' 从 'open' 更改为 'progress' 或当 'views' 列的值超过 100 时触发。在这里,我们将更新书籍被添加到关注列表时关注的计数器
class WatchList extends Model { public function onInsert($id) { $bookId = $this->get('book'); $bookModel = new Book(); $bookModel->load($bookId); $cnt = $bookModel->get('cnt_watched'); $bookModel->update(array('cnt_watched' => $cnt+1)); } }
对于对字段进行简单更新,只需将包含更改字段的关联数组传递给 update() 方法
$user = new User(); $user->load(3); // loads $user object with data fetched by given id=3 $user->update(array('first_name' => 'John', 'last_name' => 'Doe'));
## 缓存
为 Kasha 的模型库也支持缓存。
类 Kasha\Model\Cache 扩展了标准的 Kasha\Caching\Cache,包含一些处理模型数据和元数据的便捷方法。
作为库的消费者,你甚至不需要了解与缓存相关的类的内部结构,但你需要知道缓存的值存储在哪里。
目前,唯一支持的缓存存储是文件系统,因此与模型相关的缓存值存储在与Kasha框架中其他所有内容相同的/app/cache文件夹下。模型组件将确保表的元数据(文件名为[tableName].txt)存储在/app/cache/metadata下,并且与表行相对应的json对象(根据扩展Kasha\Model\Model的业务对象逻辑,可能包含更多计算数据)存储在/app/cache/data中,然后按表的名称排序存储在名为[id].txt的文件中。
例如,如果为Model库启用了缓存,并且脚本正在处理id=84的国家,那么脚本运行后,/app/cache文件夹中会出现一些新文件。
/app
/cache
/metadata
/country.txt
/models
/country
/84.txt
理论上,每个模型对象甚至可以有自己的缓存——可以使用setCache()方法设置——唯一的要求是提供的对象扩展了Model\Caching\Cache基类。
然而,在大多数情况下,使用标准的Kasha\Model\Cache就足够了——为此,您不需要明确指定任何内容。使用标准模式的一个小问题是,每个模型的构造方法都尝试通过Kasha\Model\ModelConfig类设置接收到的缓存对象。这个类反过来使用与标准Kasha\Caching\Cache相同的根文件夹路径实例化Kasha\Model\Cache,这意味着它应该在任何模型使用之前实例化。
以下是一个示例脚本来说明这一点(我们假设它在应用程序的根目录中运行)
$cache = new Cache(__DIR__ . '/app/cache/'); $country = new Country(); $list = $country->getList(array('iso2' => 'AZ'));
这段代码的第一行确保为脚本中的任何后续代码(包括其自己的子类)使用实例化了基础缓存类。
Country类的构造方法要求Kasha\Model\ModelConfig提供一个缓存实例,默认情况下将是一个Kasha\Model\Cache实例,与Kasha\Caching\Cache在相同的根文件夹中创建,在代码片段的第一行实例化。
如果需要,也可以通过提供另一个Cache类来覆盖默认行为