liqueurdetoile / cakephp-orm-json
CakePHP 插件,用于在数据库中轻松控制 JSON 类型字段
Requires
- php: ^7.2|^8.0
- adbario/php-dot-notation: ^2.1
- cakephp/cakephp: >=3.7 <5
- mustache/mustache: ^2.13
Requires (Dev)
- cakedc/cakephp-phpstan: ^2.0
- cakephp/cakephp-codesniffer: ^4.5
- cakephp/migrations: ^2.4|^3.2
- fakerphp/faker: ^1.20
- phpstan/extension-installer: ^1.1
- phpstan/phpstan: ^0.10|^1.8
- phpstan/phpstan-phpunit: ^1.1
- phpunit/phpunit: ^6|^8.5|^9.3
- vierge-noire/cakephp-test-suite-light: ^2.4
README
Cake-orm-json 插件
此分支适用于 CakePHP ^3.7|^4.0,支持 PHP ^7.2|^8.0 对于旧版本的 CakePHP,请使用此插件的 v1 版本
此插件扩展了 CakePHP ORM 的常规操作以支持 JSON 字段。它嵌入了一个特殊的 datfield 语法,允许轻松地定位 JSON 字段数据中的路径。使用它,您可以
- 选择、排序和过滤查询:
$q = $table->find('json')->where(['jfield->darn.deep.key' => true])->all()
- 在 JSON 数据内部应用数据类型
- 轻松访问、修改和删除实体中的 JSON 数据:
$e->get('jfield->darn.deep.key')
- 将 JSON 数据用作关联的外键(实际上非常极端,并不推荐,但在某些情况下可能很有用)
关系数据库并不是为了处理非模式化数据而设计的,使用 JSON 数据字段可能会引起非常差的性能。尽管如此,最新版本的数据库引擎在处理 JSON 数据方面也取得了显著的改进,NoSQL 的兴起也创造了不同的需求和限制。
注意:与 2.0.0 版本一样,它仅与 Mysql 数据库 >= 5.7.8 兼容。设置已完成,允许添加其他引擎到该插件,并希望至少为 MariaDB 和 SQLite,也许 PostgreSQL 释放它。不过,任何帮助都将非常感激:smile
- Cake-orm-json 插件
安装
安装插件
您可以使用 composer 将此插件的最新版本安装到您的 CakePHP 应用程序中。
composer require liqueurdetoile/cakephp-orm-json
插件的基命名空间为 Lqdt\OrmJson
。
重要:如果您计划使用此插件与 Cakephp 3.x,您必须通过在您的
config/bootstrap.php
中添加此行来启用兼容模式,以便设置从 Cakephp 4.x 所需的类别名。
\Lqdt\OrmJson\DatField\Compat3x::enable();
推荐设置
此插件通过复制使用的连接来升级其驱动程序,并插入一个翻译步骤,以允许将数据字段符号解析成适合cakePHP ORM使用的适当形式。显然,如果不使用数据字段符号,添加这一层是非常无用的,尽管它会消耗资源。
设置插件有许多方法来优化事物,但我们推荐这种方法,因为它将适用于大多数用例。
- 在不升级表连接的情况下添加
DatFieldBehavior
,该行为具有JSON字段,并为相应的实体添加DatFieldTrait
; - 为没有JSON字段但使用依赖于数据字段外键的关联的模型添加
DatFieldAwareTrait
; - 在查询时,如果使用数据字段符号,请始终调用
find('datfields')
或find('json')
以确保正确启用翻译。
请记住,您对使用常规或升级的连接有完全的控制权。如果您发现此设置存在性能问题,请参阅高级设置以获取更多信息。
在模型中嵌入 DatFieldAwareTrait
通常,您将在需要与其他模型通过外键(位于JSON数据中)链接的模型中使用此特性。该特性允许您基于数据字段外键链接模型,并轻松地在常规或升级的连接之间切换。
<?php namespace App\Model\Table; use Cake\ORM\Table; use Lqdt\OrmJson\ORM\DatFieldAwareTrait; class UsersTable extends Table { use DatFieldAwareTrait; // your model stuff } ?>
在模型中嵌入 DatFieldBehavior
行为提供了DatFieldAwareTrait
的所有便利性,并在创建/修补实体时处理数据字段的序列化。该行为针对包含JSON字段的模型。它还可以在序列化或持久化数据时存储永久的JSON数据类型。
<?php namespace App\Model\Table; use Cake\ORM\Table; class UsersTable extends Table { public function initialize(array $config): void { $this->addBehavior('Lqdt/OrmJson.DatField'); } } ?>
您可以将['upgrade' => true]
作为行为配置选项传递,以请求立即为模型升级连接。
行为可以在没有DatFieldTrait
的实体中使用,反之亦然。
与实体一起嵌入 DatFieldTrait
数据字段特性提供了访问和轻松操作JSON字段内容的功能。显然,它仅适用于包含JSON字段的实体。
namespace App\Model\Entity; use Cake\ORM\Entity; use Lqdt\OrmJson\Model\Entity\DatFieldTrait; class User extends Entity { use DatFieldTrait; }
该特性可以在没有DatFieldAwareTrait
或DatFieldBehavior
的模型中使用,反之亦然。
Datfield 格式
为了处理内部JSON数据,我们需要知道要使用哪个字段以及在这个字段中要使用哪个路径。显然,您可以使用SQL片段和/或原生的MySQL JSON函数,但相信我,这很容易出错,需要保护用户输入,并且,如果我们每次都必须编写原始SQL,我们还要ORM做什么呢?
此插件通过提供快速语法来定位JSON数据解决了这种困难。实际上,这个版本提供了两种方法,您可以选择或混合最适合您的方法。
此插件引入了datfield
格式(dot
和at field
的缩写),看起来像这样,并且可以像使用常规字段一样使用。通常,如果没有名称冲突,则Model
部分是可选的。
从v2开始,此插件还支持一种更对象的方法,看起来像这样
例如,假设您有一个名为position
的JSON字段,在Locations
模型中公开两个键lat
和lon
。
对于查询操作或特殊实体getter/setter,您可以考虑使用'lat@position'
或'position->lat'
来轻松操作和访问position
字段中的lat
数据。
当访问深层嵌套键时,数据字段变得特别方便:'lastknown.computed.lat@position'
(或'position->lastknown.computed.lat'
)将针对数据中的'position['lastknown']['computed']['lat']'
值。
它还部分支持JSON路径,使用与MySQL本身相同的语法来定位数组:将针对存储在path
数组中的所有项目的prop
键。
用法
快速指南
字段符号可以用于任何涉及字段的语句
// Assuming $table has DatFieldBehavior attached and its entity has DatFieldTrait attached $customers = $table->find('json') // You can mix v1 and v2 syntax at will ->select(['id', 'attributes', 'name' => 'attributes->id.person.name']) ->where(['attributes->id.person.age >' => 40]) ->order(['attributes->id.person.age']) ->all(); // Change the manager for all this customers $customers = $table->patchEntities($customers, ['attributes->manager.id' => 153]); // Update status foreach ($customers as $customer) { $total = $customer->get('attributes->command.last.total'); $stingy = $total < 50; $customer->set('attributes->status.stingy', $stingy); // You can also use array-like syntax $customer['attributes->status.vip'] = ($total > 500); // or curly syntax $customer->{'attributes->status.tobeCalled'} = !$stingy; } $table->saveMany($customers);
简而言之:就像使用常规字段一样,通过使用字段符号来定位和使用JSON数据。如果您遇到任何问题,请随时打开一个问题。
选择字段
您可以使用常规选择语句轻松选择数据中的特定路径。如果没有提供别名,它将根据字段符号创建一个复合键 <model if provided>_<field>_<path with dot replaced by underscore>
$e = $table->find()->select(['id', 'attributes->deep.nested.key'])->first(); /** Entity data will look like * [ * 'id' => 0, * 'attributes_deep_nested_key' => true * ] **/
您也可以使用字段别名来控制结果中的键
$e = $table->find()->select(['id', 'key' => 'attributes->deep.nested.key'])->first(); /** Entity data will look like * [ * 'id' => 0, * 'key' => true, * ] **/
enableAutoFields
在加载所有其他字段的同时公开一些数据时将正常工作
$e = $table->find()->select(['key' => 'attributes->deep.nested.key'])->enableAutoFields()->first(); /** Entity data will look like * [ * 'id' => 0, * 'key' => true, * 'attributes' => [ * 'deep' => [ * 'nested' => [ * 'key' => true * ] * ] * ] * ] **/
过滤和排序数据
使用datfields进行过滤或排序可以像使用其他任何字段一样,并可以通过ORM的任何常规方式完成。表达式将被自动转换为SQL中可用的表达式。您可以在任何地方使用datfields。
// Simple search using v2 datfield notation $data = $table->find()->where(['attributes->key' => 'key'])->first(); $data = $table->find()->where(['attributes->really.deep.number >=' => 10])->first(); $data = $table->find()->where(['attributes->key LIKE' => '%key%', 'attributes->really.deep.nested.key' => 'deep.nested.key'])->first(); // Looking for null will return all fields where key is missing or equals to null as default behavior $data = $table->find()->where(['attributes->fool IS' => null])->first(); // Query builder is also fine $data = $table ->find() ->where(function($exp) { return $exp->between('attributes->lastkwown.position.lat', 2.257, 2.260); }) ->first();
注意:当过滤null值时,默认行为是将任何在其JSON字段中不包含目标路径的记录也视为满足
IS NULL
条件。为了避免这种情况,您可以传递['ignoreMissingPath' => true]
作为查询选项,以仅针对其JSON字段中包含路径且值设置为null
的记录。
对于JSON格式不支持的数据类型,如datetime,有一些注意事项,但可以通过使用JSON数据类型来处理。
使用聚合和函数
datfields也得到了完全支持,可以像任何常规字段一样使用。
$q = $this->table->find(); $res = $q ->select(['kind' => 'data->group', 'total' => 'data->i + data->j', 'count' => $q->func()->count('*')]) ->group('kind') ->having(['total >' => 10]) ->distinct() ->all();
数据序列化
注意:datfields的序列化不需要升级连接
在某些情况下,您可能想在提供给createEntity
或patchEntity
方法的data中使用datfield符号,这样做没有任何问题
$e = $table->createEntity([ 'data->key' => 'foo', 'data->really.deep.key' => 'not annoying' ]); // $e will looks like [ 'id' => null, 'data' => [ 'key' => 'foo', 'really' => [ 'deep' => [ 'key' => 'not annoying' // maybe yes if having to type array ] ] ] ]
当更新实体时,默认行为是考虑数据中提供了整个JSON结构。因此,所有之前的数据都会丢失。为了避免这种情况,您可以在patchEntity
选项中传递jsonMerge
为true
或在对结果实体调用jsonMerge
(如果使用DatFieldTrait
)或通过表
// Keep our previously created entity and patch it $e = $table->patchEntity(['data->hacked' => true); // $e will looks like [ 'id' => null, 'data' => [ 'hacked' => true, ] ] // Damnit, let's restore lost data $e->jsonMerge(); // or $table->jsonMerge($e); // $e will now looks like [ 'id' => null, 'data' => [ 'hacked' => true, // Not anymore 'key' => 'foo', 'really' => [ 'deep' => [ 'key' => 'not annoying' // maybe yes if using arrays ] ] ] ] // Next time, use option $e = $table->patchEntity(['data->hacked' => true, ['jsonMerge' => true]);
您可以通过传递JSON字段名称的数组到
jsonMerge
选项或方法来微调应合并的字段:例如,['data']
实体中的 DatFieldTrait
带来了什么?
注意:使用此特性不需要升级连接或向模型添加DatFieldAwareTrait
或DatFieldBehavior
当实体使用此特性时,所有常规方法都会被替换以支持datfield符号。它们的行为保持不变,并且仍然可以用于任何常规字段。
要使用datfield获取/设置数据,只需使用get
或set
、数组类似语法或大括号语法即可
$e->get('attributes->deep.nested.value'); $e->get('deep.nested.value@attributes'); // both notations are supported $e['attributes->deep.nested.value']; $e['attributes->deep.nested.value']; $e->{'attributes->deep.nested.value'}; $e->{'deep.nested.value@attributes'};
脏状态可在路径级别和字段级别使用
$e->set('attributes->deep.nested.value', 'foo'); $e->isDirty('attributes->deep.nested.value'); // true $e->isDirty('attributes->deep.nested.othervalue'); // false $e->isDirty('attributes'); // true $e->isDirty(); // true
注意:如果您调用
setDirty('attributes', false)
,则会在attributes
中清除所有当前脏路径。
对于 PHPStan 用户
如果您正在使用PHPStan和花括号语法来访问您的数据,您无疑会遇到关于在实体上访问未定义属性的错误。为了应对这些问题,此插件提供了一个服务来检查拥有字段是否存在于实体类中,以及它是否被类型化为数组。要启用此服务,只需在您的phpstan.neon.dist
或任何配置文件中添加此片段即可
services:
-
class: Lqdt\OrmJson\PHPStan\CurlyDatFieldNotation
tags:
- phpstan.broker.propertiesClassReflectionExtension
使用 JSON 数据类型
处理JSON中的数据类型时有一些注意事项。本身JSON类型可以原生处理null和常见的标量类型:布尔值、整数、浮点或字符串,以及前者的数组和对象。当您想要处理存储在JSON中的其他类型时,问题可能开始出现,datetime就是一个完美的例子。
通常,在cakePHP中,datetime/time/date/timestamp字段被映射到FrozenTime
对象,而一个已注册的类型负责处理所需的转换。大多数情况下,此类型是从反射模式推断出来的,并且可以直接使用。
如果datetime嵌套在某些JSON数据中,它不能像这样工作,因为它仅仅是一个字符串。当处理一些常用的datetime字符串表示,如MySQL、ISO8601或时间戳时,可以简单地什么都不做,因为排序将正常工作。你只需在保存数据时传递正确的字符串格式即可。
尽管如此,你错过了datetime数据类型带来的所有便利。此外,如果你有一些糟糕的格式,查询可能会导致错误的结果。由于JSON的通用性,许多API使用自定义字符串格式,处理它们可能会很棘手。
为了简化这些问题的调试,DatFieldBehavior
允许永久或按查询定义JSON数据类型。由于JSON的通用性,它通过允许使用回调来转换数据,从而扩展了常规类型映射,而不是重复数据类型。
使用 JSON 数据类型
注意:必须升级连接才能支持JSON数据类型。
JSON数据类型存储在与升级的常规字段一起创建的升级模式中,该模式是在升级连接时创建的。因此,如果在设置它们之前没有升级,您将收到错误。
在注册JSON数据类型时,您可以选择仅提供一个字符串形式的常规数据类型,或者提供一个扩展数据类型以注册一个或多个转换操作的回调。
marshal
:当序列化数据时将调用回调。toPHP
:当处理检索到的数据时将调用回调。toDatabase
:当持久化数据时将调用回调。
所有回调都将接收目标值作为第一个参数,整个行数据作为第二个参数,以及查询(如果操作中可用)作为第三个参数。
如果为给定操作(marshal
、toPHP
或toDatabase
)提供了一个回调以及常规数据类型,则仅对数据应用回调。这样,您可以覆盖现有数据类型操作,而不是创建一个新的。
永久注册 JSON 数据类型
当使用DatfieldBehavior
时,您可以轻松且永久地注册将通过每个查询持久化的JSON类型。
// Upgrade connection if not already done $table->useDatFields(); // Register a single datfield as datetime type $table->getSchema()->setJsonTypes('data->time', 'datetime'); // Register a single datfield as date and overrides marshal hook with a callback $table->getSchema()->setJsonTypes('data->frenchDateFormat', [ 'type' => 'date', 'marshal' => function(string $value): FrozenDate { return FrozenDate::createFromFormat('d/m/Y', $value); } ]); // Register many datfields as datetime type $table->getSchema()->setJsonTypes([ 'data->time' => 'datetime', 'date->anothertime' => 'datetime' ]); // Register multiple datfields with full syntax $table->getSchema()->setJsonTypes([ 'data->time' => [ 'type' => 'datetime', 'marshal' => array($table, 'marshalTime'), // overrides datetime type marshal operation ], 'data->weirdthing' => [ // providing a type is not mandatory 'marshal' => array($table, 'importWeirdthing'), 'toPHP' => array($table, 'weirdthingToPHP'), 'toDatabase' => array($table, 'weirdthingToDatabase'), ], ]);
请注意,如果连接降级,所有JSON数据类型都将丢失,因为常规模式将被恢复。
为单个查询注册 JSON 数据类型
您还可以通过提供jsonTypeMap
选项按查询注册JSON数据类型。在发生冲突的情况下,它将覆盖模型中存储的任何JSON数据类型。
// Upgrade connection if not already done $table->useDatFields(); $q = $table->find('json', ['jsonTypeMap' => ['data->time' => 'datetime']])->all();
您还可以使用完整语法提供回调。
将模型相互链接
在DatFieldAwareTrait
和DatFieldBehavior
中都提供了特殊的升级关联。
该插件允许使用datfield表示法来引用外键并基于此关联表。它可能不如常规外键那样高效,因为外键将进行索引,但在某些边缘情况下可能很有用。
为了将datfield用作外键,只需使用任何关联的datfield对应物,并使用datfield表示法为外键选项和/或targetFoeignKey选项。
$Clients->datFieldHasOne('Agents', ['foreignKey' => 'data->agent_id']); $Clients->datFieldBelongsToMany('Products', [ 'foreignKey' => 'data->client_id' 'targetForeignKey' => 'data->product_id', 'through' => 'Orders' ]);
所有其他选项和功能保持不变。
对应物列表
belongsTo
<=>datFieldBelongsToMany
hasOne
<=>datFieldHasOne
hasMany
<=>datFieldHasMany
belongsToMany
<=>datFieldBelongsToMany
注意:不用说,连接必须升级才能使这些查询正常工作。
在MySQL中,您可以使用虚拟列将JSON数据索引为更有效率的解决方案。
CakePHP 3.x 的限制
唯一限制是,当模型通过datFieldBelongsToMany
或datFieldBelongsToManyThrough
连接时,您不能使用link
、unlink
或保存相关数据。这是由于从4.0版本发布以来,CakePHP对其处理进行了大量重构,现在无法使用此插件同时处理这两种情况。
高级设置
此插件包含
Lqdt\OrmJson\Database\Driver\DatFieldMysql
驱动:驱动程序将遍历所有查询部分,将子句中的datFields转换为MySQL的对应项,通常是JSON_EXTRACT。可以通过在查询选项中提供[useDatFields => false]
来在运行时禁用遍历;Lqdt\OrmJson\ORM\DatFieldAwareTrait
:该特性提供了方便的方法来随意升级/降级连接驱动和表模式,并引入了特殊的关联,以允许在JSON数据上链接模型;Lqdt\OrmJson\Model\Table\DatFieldBehavior
:该行为与DatFieldAwareTrait
执行完全相同的事情,同时在使用newEntity
、patchEntity
或它们的复数对应项时处理带有datfields的打包;Lqdt\OrmJson\Model\Entity\DatFieldTrait
:该特性覆盖了所有常规访问器、修改器和工具,以在实体内部处理datfield表示法,同时保持对常规字段的完全兼容性。
根据您的目标,在使用此插件时,您有多种不同的替代方案。
- 使用datfield表示法和/或JSON数据类型查询数据库或持久化数据:您必须确保将依赖于datfield表示法进行查询的模型使用升级后的连接;
- 在修补数据时使用datfield表示法:您必须在模型中嵌入
DatFieldBehavior
; - 使用datfield表示法在实体中操作数据:您必须在相关实体类中添加
DatFieldTrait
; - 使用datfield表示法链接模型:您必须使用
DatFieldAwareTrait
或DatFieldBehavior
提供的特殊关联方法;
您可以根据需要找到连接升级步骤开销和datfield转换步骤开销之间的正确平衡。
为所有模型使用升级后的驱动程序
显然,您可以在您的连接配置中简单使用升级后的驱动程序。如果所有模型都将主要使用datfield表示法,这可以是一个非常好的选择。您仍然可以通过在查询选项中提供['useDatFields' => false]
来禁用datfield转换,以避免在未使用datfields时进行无用的转换过程。
// Assuming that DatFieldAwareTrait or DatFieldBehavior are set in UsersTable $user = $this->Users ->find() // Special finder is not required here as driver is already upgraded ->where(['attributes->phones.tel' => 'wathever_number']) ->first(); $users = $this->Users ->find('all', ['useDatFields' => false]) // Disable translation overhead as not needed in this query ->all();
按模型启用或禁用升级后的驱动程序
通过将DatFieldAwareTrait
或DatFieldBehavior
添加到模型中,您可以通过使用Model::useDatFields()
/Model::useDatFields(false)
在运行时启用/禁用升级后的连接。如果您想永久在模型中使用升级后的连接,只需在initialize
钩子中调用Model::useDatFields()
或在添加行为时使用['upgrade' => true]
作为选项。您仍然可以通过在查询选项中提供['useDatFields' => false]
来按查询禁用datfield转换。
// Assuming that DatFieldAwareTrait or DatFieldBehavior are set in UsersTable // Connection is not already upgraded $user1 = $this->Users ->useDatFields() // returns model instance, so it's chainable ->find() // Special finder is not required here as driver is already upgraded ->where(['attributes->phones.tel' => 'wathever_number1']) ->first(); $user2 = $this->Users ->find() ->where(['attributes->phones.tel' => 'wathever_number2']) ->first(); $user2 = $this->Users ->find() ->where(['attributes->phones.tel' => 'wathever_number3']) ->first(); $users = $this->Users ->find('all', ['useDatFields' => false]) // Disable translation overhead as not needed in this query ->all(); // Restore genuine driver $this->Users->useDatFields(false);
注意:由于模型实例作为单例存储在注册表中,我建议在所有datfield查询解决后关闭升级后的驱动程序。
按查询使用升级后的驱动程序
这可能是最常见的情况,因为datfield查询通常都是偶尔的。通过将DatFieldAwareTrait
或DatFieldBehavior
添加到模型中,只需调用find('datfields')或find('json'),查询将使用升级后的连接,尽管模型连接仍然是真实的。您不能使用这种方式永久使用JSON数据类型,但仍然可以在查询中提供jsonTypeMap
选项。
// Assuming that DatFieldAwareTrait or DatFieldBehavior are set in UsersTable // We're in a controller that is loading Users model and connection is not already upgraded // We request connection upgrade as datfields will be used in query $user = $this->Users ->find('datfields') // or ->find('json') ->where(['attributes->phones.tel' => 'wathever_number']) ->first();
一些需要知道的小技巧
最后,当连接数据时,您可能会遇到嵌套查询的一些问题。如果您只进行单个查询,CakePHP将逻辑上用根模型的驱动填充查询连接。相反,当启动子查询时,将使用依赖模型的连接配置。
例如,假设您有一个拥有多个Locations
模型的Vehicles
模型。升级后的驱动永久用于Locations
但不在Vehicles
中。
// This will work fine because 2 databases requests will be made, 1 per model with respective connection setup $this->Vehicles->find()->contain(['Locations'])->all(); // This will fail because only 1 request with an INNER JOIN will be done from `Locations` not upgraded connection $this->Vehicles->find()->innerJoinWith('Locations', function($q) { return $q->where(['Locations.attributes->position->lat <' => 45.6]); })->all(); // This will work because we're upgrading connection on Vehicles with `datfields` custom finder // Vehicles model must at least use `DatFieldAwareTrait` $this->Vehicles->find('datfields')->innerJoinWith('Locations', function($q) { return $q->where(['Locations.attributes->position->lat <' => 45.6]); })->all();
如果您开始遇到未解析的数据字段语法错误,这意味着您在未升级的连接中使用了一些数据字段。
API 参考
请参阅API参考
与 v1.x 的区别
在之前的版本中,我们试图通过将扩展其的JsonQuery专用化来在查询中转换子句。这非常好,但它仍然仅限于查询覆盖,并且支持其他引擎显然是不可能的。
从2.0.0版本开始,翻译在MySQL驱动程序级别完成。现在的行为是创建一个新的具有新驱动程序的升级连接,该驱动程序能够在原生CakePHP ORM处理之前翻译任何数据字段表示。
CakePHP的开发者都是好人,因为他们打算计划许多覆盖,使得此插件可行。
2.x版本与1.x版本有很大的不同,因为JsonQuery现在不再需要也不可用。同样,您不需要在实体上使用任何jsonXXX
方法。常规的mutators、accessors和魔术属性将与数据字段很好地协同工作。
迁移相当简单,只需坚持使用常规查询语句,并使用select
、order
、where
代替之前的jsonSelect
、jsonOrder
、jsonWhere
。在实体中,使用常规的accessors和mutators来处理JSON中的数据。
变更日志
v2.0.0
- 重大变更:用专门处理数据字段解析的数据库驱动程序替换JsonQuery逻辑
- 重大变更:用常规访问器和mutators替换JsonXXX实体方法
- 添加v2数据字段表示支持
'[Model.]field->path'
- 完全重做和优化数据字段语法的查询翻译
- 完全重做实体的
DatFieldBehavior
和DatFieldTrait
- 将CI迁移到Github Actions
- 升级测试环境
- 添加大量测试以涵盖各种情况
v1.5.0
- 全面重做
jsonWhere
,用完整的QueryExpression
构建替换之前的条件数组解析,允许使用查询表达式回调
v1.4.0
- 添加支持在选择语句中可选地获取关联数组,而不是展平键
v1.3.0
- 添加支持在选择操作中使用点分隔符和点别名
- 添加对数据字段值排序的支持
- 添加对接受常规数据库字段到特定JSON选择、where和order语句的支持
v1.2.0
- 通过关联数组添加对
jsonSelect
和json.fields
选项中别名支持
v1.1.0
- 通过
beforeMarshal
事件和jsonmerge
添加对newEntity
和patchEntity
的支持
v1.0.0
- 添加
Lqdt\OrmJson\ORM\JsonQuery
以支持字段名称和条件的基本格式化 - 添加
Lqdt\OrmJson\Model\Behavior\JsonBehavior
以增强表中的JSON功能 - 添加
Lqdt\OrmJson\Model\Entity\JsonTrait
以增强实体中的JSON功能 - 仅支持
Mysql
免责声明
到目前为止,该插件仅将数据字段表示翻译为适当的格式,以使用CakePHP ORM执行MySQL查询。
MySQL查询方式不能直接在其他RDBMS中使用。然而,可以将该逻辑移植到其他系统,尤其是那些使用TEXT的系统。
此插件仅依赖 Mysql 的 JSON_EXTRACT 函数进行查找。其他 JSON 函数尚未实现,但可能有用(参见 Mysql 参考文档)。