martial/relationships-data-transformer

一个帮助您操作从具有关系的查询中获取数据的库

此包的规范存储库似乎已消失,因此包已被冻结。

1.0.0 2016-05-29 19:32 UTC

This package is not auto-updated.

Last update: 2022-05-06 10:25:49 UTC


README

目的

此库帮助您操作从具有关系的查询中获取的数据。

一个ORM确实可以改善您与数据库交互的方式,但它们有一个显著的缺点:它们会杀死您的应用程序性能!

如果您的首要关注点是性能,则不能使用ORM。因此,回到基本原理:您需要什么来与数据库交互?

  1. 一个数据库接口,例如PDO,或Doctrine DBAL(这是一个PDO覆盖)。Doctrine DBAL是一个不错的选择,因为它为不同类型的数据库提供抽象,有用的查询构建器和与Symfony的一等集成。当然,这是一个有效的解决方案。

  2. 仓库,因为这个模式帮助您将模型操作保存在一个地方。您的仓库将数据库连接作为依赖项。

  3. 水化器,因为我们这些现代PHP开发者更喜欢与对象而不是数组玩耍。您的水化器负责将数据库结果转换为模型对象(实体)。它们也是您仓库的依赖项。

但是,当您的查询包含关系时,实体水化可能是一场噩梦。这就是这个库出现的地方。

安装

将库添加到您的Composer依赖项

composer require 'martial/relationships-data-transformer:~1.0'

用法

确保您已加载Composer自动加载器,并创建一个RelationshipsDataTransformer实例

use Martial\RelationshipsDataTransformer\RelationshipsDataTransformer;

require __DIR__ . '/vendor/autoload.php';

$transformer = new RelationshipsDataTransformer();

现在,运行包含关系的SQL查询。例如

$query = <<<SQL
SELECT
  u.id AS user_id,
  u.username AS user_name,
  r.id AS role_id,
  r.name AS role_name,
  b.id AS book_id,
  b.name AS book_name
FROM
  users AS u
LEFT JOIN
  role AS r ON u.id = r.user_id
LEFT JOIN
  user_book AS ub ON u.id = ub.user_id
LEFT JOIN
  book AS b ON ub.book_id = b.id
SQL;

$pdo = new \PDO($params);
$statement = $pdo->prepare($query);
$rows = $statement->fetchAll(\PDO::FETCH_ASSOC);

在此阶段,您有与找到的关系一样多的行。$rows变量看起来像这样

[
    [
        'user_id' => '1',
        'user_name' => 'MartialGeek',
        'role_id' => '1',
        'role_name' => 'ROLE_ADMIN',
        'book_id' => '1',
        'book_name' => 'Linux pour les nuls'
    ],
    [
        'user_id' => '1',
        'user_name' => 'MartialGeek',
        'role_id' => '2',
        'role_name' => 'ROLE_USER',
        'book_id' => '1',
        'book_name' => 'Linux pour les nuls'
    ],
    [
        'user_id' => '1',
        'user_name' => 'MartialGeek',
        'role_id' => '1',
        'role_name' => 'ROLE_ADMIN',
        'book_id' => '2',
        'book_name' => 'I Love PHP'
    ],
    [
        'user_id' => '1',
        'user_name' => 'MartialGeek',
        'role_id' => '2',
        'role_name' => 'ROLE_USER',
        'book_id' => '2',
        'book_name' => 'I Love PHP'
    ],
    [
        'user_id' => '2',
        'user_name' => 'Doe',
        'role_id' => '3',
        'role_name' => 'ROLE_USER',
        'book_id' => '3',
        'book_name' => 'Octavia Praetexta'
    ],
    [
        'user_id' => '2',
        'user_name' => 'Doe',
        'role_id' => '3',
        'role_name' => 'ROLE_USER',
        'book_id' => '4',
        'book_name' => 'C. Iuli Caesaris De Bello Gallico'
    ],
];

迭代这些行在将结果水化为对象时是一个噩梦。因此,在将它们水化之前,调用数据转换器的transform方法并使用选项来组织您的数据

$mergedRelationships = $transformer->transform($rows, [
    RelationshipsDataTransformer::OPTION_ROOT_PRIMARY_KEY => 'user_id',
    RelationshipsDataTransformer::OPTION_RELATIONSHIPS => [
        'roles' => [
            RelationshipsDataTransformer::OPTION_PREFIX => 'role_',
            RelationshipsDataTransformer::OPTION_PRIMARY_KEY => 'role_id',
            RelationshipsDataTransformer::OPTION_REFERENCE_COLUMN => 'user_id'
        ],
        'books' => [
            RelationshipsDataTransformer::OPTION_PREFIX => 'book_',
            RelationshipsDataTransformer::OPTION_PRIMARY_KEY => 'book_id',
            RelationshipsDataTransformer::OPTION_REFERENCE_COLUMN => 'user_id'
        ],
    ]
]);

所有这些选项都是强制性的,以定义您的关联

  1. RelationshipsDataTransformer::OPTION_ROOT_PRIMARY_KEY:定义查询主表的主键(在“from”子句中)

  2. RelationshipsDataTransformer::OPTION_RELATIONSHIPS:包含关联定义数组。每个子键代表一个关系名称。在这里,“roles”存储在“roles”子键中,而书籍在“books”键中。

  3. RelationshipsDataTransformer::OPTION_PREFIX:当前关系的行的前缀。对于角色,我们使用了别名“role_”来前缀相关结果。然后数据转换器将查找此前缀以在行中查找相关数据。

  4. RelationshipsDataTransformer::OPTION_PRIMARY_KEY:关系的主键。一旦从数据库结果中提取了关系数据,库就会使用此信息来找到合并相关数据的位置。

  5. RelationshipsDataTransformer::OPTION_REFERENCE_COLUMN:关系引用列,如您的表定义中定义的那样。需要此信息以知道库何时必须创建当前关系的新行集。

现在,$mergedRelationships数组看起来像这样

[
    [
        'user_id' => '1',
        'user_name' => 'MartialGeek',
        'roles' => [
            [
                'id' => '1',
                'name' => 'ROLE_ADMIN'
            ],
            [
                'id' => '2',
                'name' => 'ROLE_USER'
            ]
        ],
        'books' => [
            [
                'id' => '1',
                'name' => 'Linux pour les nuls'
            ],
            [
                'id' => '2',
                'name' => 'I Love PHP'
            ]
        ]
    ],
    [
        'user_id' => '2',
        'user_name' => 'Doe',
        'roles' => [
            [
                'id' => '3',
                'name' => 'ROLE_USER'
            ]
        ],
        'books' => [
            [
                'id' => '3',
                'name' => 'Octavia Praetexta'
            ],
            [
                'id' => '4',
                'name' => 'C. Iuli Caesaris De Bello Gallico'
            ]
        ]
    ]
];

水化您的数据非常简单

$hydrator = new My\Hydrator();
$users = [];

foreach ($mergedRelationships as $row) {
      $users[] = $hydrator->hydrate($row);
}

在您的加湿器中,您通过迭代关系键 "books" 和 "roles" 来构建相关实体。