从关系数据库映射数据

有时会出现这样的情况,例如从关系数据库检索数据的解决方案不适合项目中使用的ORM的功能,例如,由于ORM本身的速度不足,或者由于ORM自身生成的SQL查询不是很理想。在这种情况下,通常必须手动编写查询。

问题是来自数据库的数据(包括响应JOIN请求的数据)作为“平面”二维数组返回,该二维数组不反映应用程序数据的复杂“树”结构。进一步使用这样的阵列非常不方便,因此,需要或多或少的通用解决方案以根据给定的图案将该阵列变成更合适的形式。

找到了解决方案,既方便又快速。

多快


为了评估库的速度,我建立了一个小型测试台,将库的速度与Eloquent的速度进行了比较。为了进行测量,使用了phpbench软件包。

为了在家中部署展台:

git clone https://github.com/hrustbb2/env-arrayproc-bench.git
cd env-arrayproc-bench
./env

在这里,我使用了上一篇文章中介绍的工具

然后在菜单中选择:1开发,然后:1构建,然后2部署和升级;
然后运行测试5.运行测试

数据库中有3000本书。结果如下:

+-----------------+-----+------+------+-------------+--------------+
| subject         | set | revs | iter | mem_peak    | time_rev     |
+-----------------+-----+------+------+-------------+--------------+
| benchEloquent   | 0   | 1    | 0    | 76,442,912b | 12,781.612ms |
| benchEloquentId | 0   | 10   | 0    | 5,123,224b  | 16.432ms     |
| benchProc       | 0   | 1    | 0    | 36,364,176b | 1,053.937ms  |
| benchProcId     | 0   | 10   | 0    | 4,462,696b  | 7.684ms      |
+-----------------+-----+------+------+-------------+--------------+

benchEloquent -翻出所有用雄辩的作者的书
benchEloquentId -翻出某本书用佞(10倍)的作者

benchProc -翻出所有使用该库的作者的书
benchProcId -翻出了某本书使用的库(10)作者

以开动测试的代表性不足,但是在运行时和内存消耗方面,差异是显而易见的。

怎么运行的


安装:

composer require hrustbb2/arrayproc:v1.0.0

此外,以一个示例(极其简单)为例,假设我们有一个具有以下结构的书籍和作者数据库。

图片

任务是将所有书籍与其作者一起拿走。

该请求将如下所示:

SELECT
    books.id,
    books.name,
    authors.id,
    authors.name
FROM
    books
LEFT JOIN relations ON relations.books_id = books.id
LEFT JOIN authors ON authors.id = relations.authors_id

作为回应,我们得到了这样一个数据数组。

book.idbook.nameauthor.idauthor.name
1个书12作者2
1个书14作者4
1个书16作者6
2书22作者2
2书23作者3
2书26作者6
2书27作者7


该数组是二维的,某些字段是重复的,为方便起见,您需要对其进行转换
[
	1 => [
		'id' => 1,
		'name' => 'book1',
		'authors' => [
			2 => [
				'id' => 2,
				'name' => 'author2'
			],
			4 => [
				'id' => 4,
				'name' => 'author4'
			],
			6 => [
				'id' => 6,
				'name' => 'author6'
			],
		]
	],
	2 => [
		'id' => 2,
		'name' => 'book2',
		'authors' => [
			2 => [
				'id' => 2,
				'name' => 'author2'
			],
			3 => [
				'id' => 3,
				'name' => 'author3'
			],
			6 => [
				'id' => 6,
				'name' => 'author6'
			],
			7 => [
				'id' => 7,
				'name' => 'author7'
			],
		]
	],
]


为此,请略微修改我们的要求:


SELECT
    books.id AS book_id,
    books.name AS book_name,
    authors.id AS author_id,
    authors.name AS author_name
FROM
    books
LEFT JOIN relations ON relations.books_id = books.id
LEFT JOIN authors ON authors.id = relations.authors_id

在这里,我们在SELECT部分​​中设置别名:对于带有有关书籍数据的字段,对于带有前缀“ book_”的别名,对于带有关于作者信息的字段,带有前缀“ author”。

接下来,我们转换数据库响应

use hrustbb2\arrayproc\ArrayProcessor;

$arrayProcessor = new ArrayProcessor();
$config = [
	'prefix' => 'book_',
	'authors' => [
		'prefix' => 'author_',
	]
]
$booksData = $arrayProcessor->process($conf, $rows)->resultArray();

其中:

$ rows是对象数组形式的数据库响应/ stdClass()
$ config是反映所得数组数据结构的关联数组

结果,在$ booksData中,我们有一个树状数组,其结构在$ config中描述,并填充了相应的数据。

这样的东西。

All Articles