用于JSON文件和字符串的查询语言,由PHP构建

1.1.1 2019-10-30 22:47 UTC

This package is auto-updated.

Last update: 2024-08-29 05:18:27 UTC


README

JSON查询语言(JQL - 发音为 "jackal")是一个用PHP编写的查询语言系统,用于查询JSON字符串和文件。它还支持PHP stdClass 对象。这种“语言”在SQL(流行的数据库查询语言)的基础上构建,以便于采用和学习,但确实有一些限制,因为SQL的一些高级功能无法实现。

在阅读完整文档之前,请查看最小示例,以更好地理解如何使用JQL。

目录

  1. 安装
  2. 使用
  3. 函数参考
  4. 本地化
  5. 示例
  6. 要求
  7. 路线图
  8. 许可证

1. 安装

安装JQL库的最简单方法是使用Composer。要将JQL添加到您的项目中,只需从终端运行以下Composer命令

$ composer require benmajor/jql

或者,从存储库的src/目录下载所有源文件,并将它们包含到您的项目中。

2. 使用

JQL旨在让网页开发者易于使用;其语法基于SQL,尽管功能更有限,但结果符合预期。目的是构建一个简单高效的JSON和PHP数据结构的查询语言。使用相对简单直接,但建议查阅示例,以从JQL中获得最佳结果。

要开始,只需使用数据集调用JQL构造函数。构造函数接收单个参数,可以是以下任何一种

  • JSON编码的字符串
  • 包含文件指针的字符串
  • PHP对象数组

例如,以下所有构造函数都是有效的

使用JSON编码的字符串

$jql = new JQL('[{
    'id':      2,
    'name':    'John',
    'surname': 'Doe'
}]');

指向有效JSON文件的指针

$jql = new JQL('MyDataset.json');

PHP对象数组 / 关联数组

$jql = new JQL([
  [
    'id'      => 1,
    'name'    => 'John',
    'surname' => 'Doe'
  ]
]);

构造函数将返回一个新的JQL对象,可以对其执行函数,或者您也可以对数据执行类似SELECT的查询,返回特定列,并按特定数量和/或偏移量排序结果。以下部分将提供选择、更新、排序和限制数据的详细信息。

选择特定列

创建JQL对象后,您应调用select()方法来从JSON数据请求特定列。

应指定多个字段为数组,但您始终可以通过将包含*的字符串传递给select()函数来请求所有字段,如下所示

$jql->select( '*' );

或者,您可以通过将它们作为数组传递来指定要检索的特定列

$jql->select([ 'name', 'surname' ]);

上述代码将只返回指定数据集中每个对象的namesurname字段。

除了返回特定的列之外,JQL 还内置了可以在选择之前调用在字段上的函数。JQL 的多数内置函数都是基于 SQL 函数,并且以类似的方式工作。遗憾的是,由于 SQL 的复杂性以及本库旨在保持快速和高效的宗旨,无法在一次数据遍历中调用多个函数。

以下是一个使用两个函数调用的 select() 例子

$jql->select([
  'LCASE(name) AS name_lower',
  'CURRENT_TIMESTAMP() AS timestamp'
]);

有关函数和例子的完整列表,请参阅本文档的 函数参考 部分。

JQL 还能够返回字段别名,这可以通过使用 AS 关键字实现。当你需要用比原始列名更短的引用来引用字段时,这特别有用。例如,在上面的代码片段中,name_lower 是一个不存在于原始数据结构中的别名字段。别名也可以不用函数使用,例如

$jql->select([
  'super_long_column_name AS id'
]);

更新特定列

除了选择字段外,JQL 还能够更新原始数据结构中的字段。这是通过使用 update() 方法实现的,该方法与 where() 方法(详情请见)结合使用时特别有用。

$jql->update([
  'name' => 'NAME REPLACED'
]);

JQL 还具有在更新列时可以使用的内置函数。有关使用 update() 方法时可以使用的函数的详细信息,请参阅 函数参考

使用 where() 搜索数据

where() 方法的工作方式类似于 SQL 的 WHERE 子句,可以用来快速筛选 select()update() 方法的结果。

where() 方法接受一个由 ANDOR 分隔的单独的条款字符串。截至撰写本文时,JQL 不支持组合条款,如 ANDOR,只能使用其中一个。

为了筛选所有 age 列值 > 10 的记录,我们可以使用

$jql->select('forename')->where('age > 10');

JQL 支持以下操作符与 where() 方法一起使用

排序结果

JQL 能够根据指定的列值对数据进行排序。可以使用多个列进行排序,并且可以指定每个列的顺序,如下所示

$jql->select('forename')->order('surname', 'ASC');

上述代码片段将按 surname 列的值升序排序结果。可以通过将多个列添加到 order() 中来排序数据,例如,要按 surname 升序和 age 降序排序,我们可以执行以下操作

$jql->select('forename')->order('surname', 'ASC')->order('age', 'DESC');

限制结果

我们还可以使用 limit() 限制结果的数量,与 offset() 结合使用时特别强大。例如,以下代码片段只检索前两个匹配的记录

$jql->select('forename')->where('age > 10')->limit(2);

还可以将偏移量指定为 limit() 方法的第二个参数。例如,以下代码片段将返回 2 个结果,第一个结果将被跳过

$jql->select('forename')->where('age > 10')->limit(2, 1);

您还可以使用 offset() 方法单独指定偏移量,如下所示(以下代码片段与上面显示的代码片段相同)

$jql->select('forename')->where('age > 10')->limit(2)->offset(1);

执行查询

一旦使用 select()update() 方法设置完查询,就可以实际执行查询了。这可以通过 JQl 中的一系列函数来实现,具体取决于所需的查询结果。

fetch():
fetch() 方法将返回一个包含所有结果匹配项的数组,限制在指定的限制和偏移量内,并按指定的列排序。如果没有找到匹配项,则该函数返回 NULL

fetchOne():
fetchOne() 方法将返回匹配集的第一条结果。它将以对象的形式返回,而不是数组。如果没有找到匹配项,则该函数返回 NULL

fetchAsJSON( $prettyPrint = false ):
fetchAsJSON 方法与 fetch() 相同,但它返回一个 JSON 编码的字符串,而不是 PHP 数组。此函数接受一个参数,可以用来指定返回的 JSON 是否是格式化的(默认为 false)—— 必须是一个有效的布尔值。

fetchOneAsJSON():
与上述相同,但针对第一条记录。

saveAsFile( $pointer ):
将结果数据保存到位于 $pointer 的 JSON 文件中。

count():
简单返回表示受影响行数的整数。

3. 函数参考

所有函数都可以在 JSON 结构中出现的列或固定字符串(类似于 SQL)上调用。例如,以下两个都会产生相同的结果

$json = [ 
  [
    'id' => 1,
    'forename' => 'John',
    'surname' => 'Doe'
  ]
];

$jql = new JQL($json);

$jql->select([ 'UPPER(forename)' ]); # Returns JOHN for the first record.
$jql->select([ 'UPPER(John)' ]);     # Returns JOHN for ALL records.

select() 函数

以下函数可以与 select() 方法一起使用

字符串函数

数字函数

日期函数

聚合函数

update() 函数

以下函数可以与 update() 方法一起使用

  • APPEND
  • CONCAT_WS
  • LCASE
  • LEFT
  • LOWER
  • LPAD
  • LTRIM
  • PREPEND
  • REPLACE
  • REVERSE
  • RIGHT
  • RPAD
  • RTRIM
  • SUBSTR
  • SUBSTRING
  • TRIM
  • UCASE
  • UPPER

6. 本地化

JQL 可以返回服务器的当前日期和时间,以及日期的月份和日名称。因此,它已经开发了一些内置的本地化选项,这些选项有助于处理多语言应用程序。如果您需要其他语言的月份和日名称,必须首先调用 setLocale() 方法

$jql->setLocale('nl_NL');

上面的代码将当前区域设置设置为 nl_NL

要处理时间函数的不同时区,只需调用 setTimezone() 并指定所需的时区

$jql->setTimezone('Europe/Paris');

5. 示例

本节包含一些示例,演示了 JQL 的使用方法。如果在您的编码过程中发现任何函数没有按预期工作,请通过 Github 存储库提出问题。

以下所有示例都假设以下 JSON 结构

[
  {
    'id': 1,
    'forename': 'John',
    'surname':  'Doe',
    'age': 25,
    'birthday': '1995-05-24',
    'tags': [ 'red', 'green' ]
  },
  {
    'id': 2,
    'forename': 'Joe',
    'surname': 'Bloggs',
    'age': 50,
    'birthday': '1955-02-24',
    'tags': [ 'red', 'blue' ]
  },
  {
    'id': 3,
    'forename': 'Foo',
    'surname': 'Bar',
    'age': 12,
    'birthday': '2007-12-09',
    'tags': [ ]
  },
  {
    'id': 4,
    'forename': 'John',
    'surname': 'Boy',
    'age': 19,
    'birthday': '2018-09-09'
  }
]

最小工作示例

选择每个用户的姓名和姓氏,按姓氏和名字排序

$jql = new JQL($json);

$jql->select([ 'forename', 'surname' ])
    ->order('surname', 'ASC')
    ->order('forename', 'ASC')
    ->fetch();

使用函数

通过连接他们的 forenamesurname 字段来返回每个用户的完整姓名

$jql = new JQL($json);

$jql->select([ 'CONCAT_WS(forename, surname, \' \') AS full_name' ])
    ->fetch();

使用聚合函数

获取所有用户的平均年龄

$jql = new JQL($json);

$jql->select([ 'AVG(age) AS average_age' ])
    ->fetchOne();

使用 where()

检索标记为 red 的所有用户的平均年龄和连接的完整姓名

$jql = new JQL($json);

$jql->select([ 'AVG(age) AS average_age', 'CONCAT_WS(forename, surname, \' \') AS full_name' ])
    ->where('tags CONTAINS red')
    ->fetch()

更新记录

将用户 1 更新为包含完整姓名的新字段,并将更新后的结果保存到名为 updated.json 的 JSON 文件中

$jql = new JQL($json);

$jql->update([ 'full_name' => 'CONCAT_WS(forename, surname, \' \') AS full_name' ])
    ->where('id = 1')
    ->saveAsFile('updated.json');

日期函数

选择用户出生的日期,这些用户被称为 John 并且年龄大于 18

$jql = new JQL($json);

$jql->select([ 'DAYNAME(birthday) AS birth_day' ])
    ->where( 'forename = John AND age > 18' )
    ->fetch();

6. 需求

JQL 是自包含的,没有外部库或框架依赖。但是,为了正常工作,以下是最小的 PHP 要求:

  • PHP 版本 >= 5.6
  • 启用 PHP json 模块

7. 路线图

JQL 仍在开发中,有许多功能我打算添加到库中。如果您想为项目做出贡献,请与我联系!

  • 支持远程 JSON 文件
  • 支持多种 WHERE 子句类型(包括 ANDOR

8. 许可证

MIT 许可证

版权所有 (c) 2019 Ben Major

特此授予任何获得本软件及其相关文档副本(以下简称“软件”)的人免费使用的许可,不受限制地处理该软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件的副本,并允许向提供软件的人做此类事情,但需遵守以下条件:

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

软件按“原样”提供,不提供任何形式的保证,明示或暗示,包括但不限于对适销性、适用于特定目的和无侵犯性的保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任负责,无论该责任是基于合同、侵权或其他原因,无论该索赔、损害或其他责任是否源于、源于或与软件或软件的使用或其他交易有关。