martial / relationships-data-transformer
一个帮助您操作从具有关系的查询中获取数据的库
此包的规范存储库似乎已消失,因此包已被冻结。
Requires (Dev)
- mockery/mockery: ~0.9
- phpunit/phpunit: ~5.3
This package is not auto-updated.
Last update: 2022-05-06 10:25:49 UTC
README
目的
此库帮助您操作从具有关系的查询中获取的数据。
一个ORM确实可以改善您与数据库交互的方式,但它们有一个显著的缺点:它们会杀死您的应用程序性能!
如果您的首要关注点是性能,则不能使用ORM。因此,回到基本原理:您需要什么来与数据库交互?
-
一个数据库接口,例如PDO,或Doctrine DBAL(这是一个PDO覆盖)。Doctrine DBAL是一个不错的选择,因为它为不同类型的数据库提供抽象,有用的查询构建器和与Symfony的一等集成。当然,这是一个有效的解决方案。
-
仓库,因为这个模式帮助您将模型操作保存在一个地方。您的仓库将数据库连接作为依赖项。
-
水化器,因为我们这些现代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' ], ] ]);
所有这些选项都是强制性的,以定义您的关联
-
RelationshipsDataTransformer::OPTION_ROOT_PRIMARY_KEY:定义查询主表的主键(在“from”子句中)
-
RelationshipsDataTransformer::OPTION_RELATIONSHIPS:包含关联定义数组。每个子键代表一个关系名称。在这里,“roles”存储在“roles”子键中,而书籍在“books”键中。
-
RelationshipsDataTransformer::OPTION_PREFIX:当前关系的行的前缀。对于角色,我们使用了别名“role_”来前缀相关结果。然后数据转换器将查找此前缀以在行中查找相关数据。
-
RelationshipsDataTransformer::OPTION_PRIMARY_KEY:关系的主键。一旦从数据库结果中提取了关系数据,库就会使用此信息来找到合并相关数据的位置。
-
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" 来构建相关实体。