liqueurdetoile/cakephp-orm-json

CakePHP 插件,用于在数据库中轻松控制 JSON 类型字段

安装次数: 32,834

依赖关系: 0

建议者: 0

安全: 0

星标: 13

关注者: 1

分支: 3

开放问题: 0

类型:cakephp-plugin

2.0.0 2022-09-08 17:18 UTC

This package is auto-updated.

Last update: 2024-08-29 21:01:49 UTC


README

Latest Stable Version 2.x-next status Coverage Status PR_Welcome license

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

安装

安装插件

您可以使用 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;
}

该特性可以在没有DatFieldAwareTraitDatFieldBehavior的模型中使用,反之亦然。

Datfield 格式

为了处理内部JSON数据,我们需要知道要使用哪个字段以及在这个字段中要使用哪个路径。显然,您可以使用SQL片段和/或原生的MySQL JSON函数,但相信我,这很容易出错,需要保护用户输入,并且,如果我们每次都必须编写原始SQL,我们还要ORM做什么呢?

此插件通过提供快速语法来定位JSON数据解决了这种困难。实际上,这个版本提供了两种方法,您可以选择或混合最适合您的方法。

此插件引入了datfield格式(dotat field的缩写),看起来像这样,并且可以像使用常规字段一样使用。通常,如果没有名称冲突,则Model部分是可选的。

从v2开始,此插件还支持一种更对象的方法,看起来像这样

例如,假设您有一个名为position的JSON字段,在Locations模型中公开两个键latlon

对于查询操作或特殊实体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的序列化不需要升级连接

在某些情况下,您可能想在提供给createEntitypatchEntity方法的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选项中传递jsonMergetrue或在对结果实体调用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 带来了什么?

注意:使用此特性不需要升级连接或向模型添加DatFieldAwareTraitDatFieldBehavior

当实体使用此特性时,所有常规方法都会被替换以支持datfield符号。它们的行为保持不变,并且仍然可以用于任何常规字段。

要使用datfield获取/设置数据,只需使用getset、数组类似语法或大括号语法即可

$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:当持久化数据时将调用回调。

所有回调都将接收目标值作为第一个参数,整个行数据作为第二个参数,以及查询(如果操作中可用)作为第三个参数。

如果为给定操作(marshaltoPHPtoDatabase)提供了一个回调以及常规数据类型,则仅对数据应用回调。这样,您可以覆盖现有数据类型操作,而不是创建一个新的。

永久注册 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();

您还可以使用完整语法提供回调。

将模型相互链接

DatFieldAwareTraitDatFieldBehavior中都提供了特殊的升级关联。

该插件允许使用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 的限制

唯一限制是,当模型通过datFieldBelongsToManydatFieldBelongsToManyThrough连接时,您不能使用linkunlink或保存相关数据。这是由于从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执行完全相同的事情,同时在使用newEntitypatchEntity或它们的复数对应项时处理带有datfields的打包;
  • Lqdt\OrmJson\Model\Entity\DatFieldTrait:该特性覆盖了所有常规访问器、修改器和工具,以在实体内部处理datfield表示法,同时保持对常规字段的完全兼容性。

根据您的目标,在使用此插件时,您有多种不同的替代方案。

  • 使用datfield表示法和/或JSON数据类型查询数据库或持久化数据:您必须确保将依赖于datfield表示法进行查询的模型使用升级后的连接;
  • 在修补数据时使用datfield表示法:您必须在模型中嵌入DatFieldBehavior
  • 使用datfield表示法在实体中操作数据:您必须在相关实体类中添加DatFieldTrait
  • 使用datfield表示法链接模型:您必须使用DatFieldAwareTraitDatFieldBehavior提供的特殊关联方法;

您可以根据需要找到连接升级步骤开销和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();

按模型启用或禁用升级后的驱动程序

通过将DatFieldAwareTraitDatFieldBehavior添加到模型中,您可以通过使用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查询通常都是偶尔的。通过将DatFieldAwareTraitDatFieldBehavior添加到模型中,只需调用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和魔术属性将与数据字段很好地协同工作。

迁移相当简单,只需坚持使用常规查询语句,并使用selectorderwhere代替之前的jsonSelectjsonOrderjsonWhere。在实体中,使用常规的accessors和mutators来处理JSON中的数据。

变更日志

v2.0.0

  • 重大变更:用专门处理数据字段解析的数据库驱动程序替换JsonQuery逻辑
  • 重大变更:用常规访问器和mutators替换JsonXXX实体方法
  • 添加v2数据字段表示支持 '[Model.]field->path'
  • 完全重做和优化数据字段语法的查询翻译
  • 完全重做实体的DatFieldBehaviorDatFieldTrait
  • 将CI迁移到Github Actions
  • 升级测试环境
  • 添加大量测试以涵盖各种情况

v1.5.0

  • 全面重做jsonWhere,用完整的QueryExpression构建替换之前的条件数组解析,允许使用查询表达式回调

v1.4.0

  • 添加支持在选择语句中可选地获取关联数组,而不是展平键

v1.3.0

  • 添加支持在选择操作中使用点分隔符和点别名
  • 添加对数据字段值排序的支持
  • 添加对接受常规数据库字段到特定JSON选择、where和order语句的支持

v1.2.0

  • 通过关联数组添加对jsonSelectjson.fields选项中别名支持

v1.1.0

  • 通过beforeMarshal事件和jsonmerge添加对newEntitypatchEntity的支持

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 参考文档)。