spinitron / yii2-dynamic-ar
扩展 Yii ActiveRecord 以支持 Maria Dynamic Columns
Requires
- yiisoft/yii2: ~2.0
Requires (Dev)
- phpunit/phpunit: ~4.4
- yiisoft/yii2-apidoc: ~2.1
- yiisoft/yii2-bootstrap: *
- yiisoft/yii2-coding-standards: ~2.0.2
- yiisoft/yii2-dev: ~2.0
This package is not auto-updated.
Last update: 2024-09-18 10:33:25 UTC
README
yii2-dynamic-ar 扩展为 Yii 2 框架 的 Active Record ORM 添加了类似 NoSQL 的文档。
Maria Dynamic Columns 和 PostgreSQL jsonb
Maria 10.0+ 中的 Dynamic Columns 以及 PostgreSQL 9.4+ 中的 jsonb 列类型和 函数 实际上为 SQL 表的每一行附加了一个 NoSQL 文档。这是一个强大的功能,允许你做一些在关系型数据库中难以完成的事情。可能会让你转向 Couch 或 Mongo,或者在模式中实施类似 EAV 的犯罪,现在突然变得容易了。
- 记录可以有任意数量的属性,
- 属性名称可以即时生成,
- 动态属性名称不会出现在模式中,
- 动态属性可以像关联数组一样结构化。
Dynamic AR 目前适用于 Maria,未来将支持 PostgreSQL。
示例
一个在线购物网站有一个表格,用于存储关于每个产品的信息。
CREATE TABLE product ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, sku VARCHAR(32), upc VARCHAR(32), title VARCHAR(255), price DECIMAL(9, 2), stock INT(11), details LONGBLOB NOT NULL );
在这个(简化的)示例中,details
将包含 Maria 的 Dynamic Column blob,并通过模型类中的 dynamicColumn()
方法声明。Dynamic AR 类声明中的其他内容都是熟悉的 AR 内容。
class Product extends \spinitron\dynamicAr\DynamicActiveRecord { public static function tableName() { return 'product'; } public static function dynamicColumn() { return 'details'; } }
现在我们可以使用 Product
做所有正常的 AR 事情,但除此之外,我们还可以读取、写入和更新方案中未提及的属性。
$product = new Product([ 'sku' => 5463, 'upc' => '234569', 'price' => 4.99, 'title' => 'Clue-by-four', 'description' => 'Used for larting lusers or constructing things', 'dimensions' => [ 'unit' => 'inch', 'width' => 4, 'height' => 2, 'length' => 20, ], 'material' => 'wood', ]); $product->save();
将 details
表列视为包含序列化的关联数组。但与在文本字段中保存 JSON 文档不同,你可以在代码的任何地方使用动态属性,包括在查询中,就像使用方案属性一样。区别在于
- 嵌套属性使用点表示法,例如
dimensions.length
- 在模型实例上直接获取和设置嵌套属性使用
getAttribute()
和setAttribute()
方法,因为 PHP 不允许在标识符中使用点表示法。 - 当动态属性出现在查询中时,用感叹号括号
(! … !)
包围它,例如(! dimensions.length !)
。(属性名称与其感叹号括号之间的空格是可选的,因此(!material!)
也是可以的。)
例如
$model = new Product([ 'title' => 'Car', 'specs.fuel.tank.capacity' => 50, 'specs.fuel.tank.capacity.unit' => 'liter', ]); $model->setAttribute('specs.wheels.count', 4); $model = Product::find()->where(['(!dimensions.length!)' => 10]); $section = Product::find() ->select('CONCAT((! dimensions.width !), " x ", (! dimensions.height !))') ->where(['id' => 11]) ->one();
点表示法可以在 Yii 接受属性名称字符串的地方使用,例如
class Product extends \spinitron\dynamicAr\DynamicActiveRecord { public function rules() { return [['dimensions.length', 'double', 'min' => 0.0]]; } public function search($params) { $dataProvider = new \yii\data\ActiveDataProvider([ 'sort' => [ 'attributes' => [ 'dimensions.length' => [ 'asc' => ['(! dimensions.length !)' => SORT_DESC], 'desc' => ['(! dimensions.length !)' => SORT_ASC], ], ], ], // ... ]); } }
设计原则
DynamicActiveRecord 将第四个功能添加到读取和写入 AR 模型属性可以做的事情中
$model->foo
如果存在,则访问实例变量$foo
,- 否则它将访问列属性
foo
,如果模型的表中存在列“foo”, - 否则它将访问虚拟属性
foo
,如果模型的类有魔法getFoo()
/setFoo()
方法, - 否则
$model->foo
将访问一个名为“foo”的动态属性。
所以任何不指向正常三种AR模型属性(实例变量、列属性、虚拟属性)之一的属性名,一旦使用,就自动成为动态属性。无法声明动态属性,只能通过写入来定义。
读取不存在的属性将返回null。
PHP null,SQL NULL 和 Maria
Maria不会对设置为SQL NULL的动态列进行编码
SELECT COLUMN_CREATE('a', 1, 'b', null) = COLUMN_CREATE('a', 1) >> 1
因此,如果一个表记录当前有一个名为'b'的动态列,而Maria执行更新将其设置为NULL,那么Maria将从记录中删除'b'。(如果NULL具有数据库中传统意义上的“数据值不存在”,则这有意义。)因此,DynamicActiveRecord在从数据库读取回后不可能区分NULL值和不存在于动态列。
为了保持一致性,DynamicActiveRecord在读取尚未设置的动态属性时始终返回null,而ActiveRecord会抛出异常。但根据设计原则(如上所述),如果null表示“不存在”,则这也有道理。
进一步阅读
类参考
更多文档
- PHP、SQL和JSON中的数据类型并不相同。
- 设计历史 - 项目原始的README。
有用的链接
在gh-pages分支中重新生成文档
vendor/bin/apidoc api . . --template="spinitron\dynamicAr\doc\template\ApiRenderer"
问题、评论、问题
使用问题跟踪器。或者如果您更喜欢,可以轻松找到我的电子邮件。
版权(c)2015 Spinitron LLC