Sometimes situations arise when the solution to the problem of retrieving data from a relational database does not fit into the capabilities of the ORM used in the project, for example, either because of the insufficient speed of the ORM itself, or not quite optimal SQL queries generated by it. In this case, you usually have to write queries manually.The problem is that the data from the database (including in response to the JOIN request) is returned as a โflatโ two-dimensional array that does not reflect the complex โtree-likeโ data structure of the application. It is extremely inconvenient to work with such an array further, therefore, a more or less universal solution is required to bring this array into a more suitable form according to a given pattern.The solution was found, convenient and fast enough.How fast
To evaluate the speed of the library, I put together a small test bench on which the speed of my library is compared with the speed of Eloquent. For measurements, the phpbench package was used.In order to deploy a stand at home:git clone https://github.com/hrustbb2/env-arrayproc-bench.git
cd env-arrayproc-bench
./env
Here I used the tool described in my previous article .Then in the menu we select: 1 Develop, then: 1 Build, then 2 Deploy and Up;Then run the tests 5. Run testsThere are 3000 books in the database. The results are as follows:+-----------------+-----+------+------+-------------+--------------+
| 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 - pulls out all the books with the authors using EloquentbenchEloquentId - pulls out a certain book with the authors using Eloquent (10 times)benchProc - pulls out all the books with the authors using the librarybenchProcId - pulls out a certain book with the authors using the library (10)to actuate tests are not representative enough, but the difference is noticeable, both in runtime and in memory consumption.How it works
Install:composer require hrustbb2/arrayproc:v1.0.0
Further, for an example (extremely simple), imagine that we have a database of books and authors with the following structure.
The task is to pull out all the books with their authors.The request will look something like this: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
In response, we get about such an array of data.The array is two-dimensional, some fields are duplicated, for convenience you need to convert it[
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'
],
]
],
]
To do this, slightly modify our request:
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
Here we set aliases in the SELECT section: for fields with data about books, aliases with the prefix 'book_', and for fields with information about authors with the prefix 'author'.Next, we convert the database responseuse hrustbb2\arrayproc\ArrayProcessor;
$arrayProcessor = new ArrayProcessor();
$config = [
'prefix' => 'book_',
'authors' => [
'prefix' => 'author_',
]
]
$booksData = $arrayProcessor->process($conf, $rows)->resultArray();
where:$ rows is the database response in the form of an array of objects / stdClass ()$ config is an associative array reflecting the data structure of the resulting arrayAs a result, in $ booksData we have a tree-like array having the structure described in $ config, filled with the corresponding data.Something like this.