libertyphp/datamapper
LibertyPHP Datamapper。适用于MySQL和PostgreSQL的简单而强大的数据映射器。
1.1
2021-10-01 05:39 UTC
Requires
- php: ^7.4|^8.0
- ext-pdo: *
- ext-pgsql: *
Requires (Dev)
- phpunit/phpunit: ^9.5.4
This package is auto-updated.
Last update: 2024-09-29 06:03:02 UTC
README
适用于MySQL和PostgreSQL的简单而强大的数据映射器。
项目哲学
- 活动记录模式是反模式。它违反了面向对象编程的SOLID原则。此外,活动记录模式的模型通常过于复杂,这会导致性能下降。
- 存储库模式不是与关系数据库交互的最佳解决方案。此模式过于抽象。这导致代码复杂性和性能下降。
- 查询构建器不是制作SQL查询的最佳解决方案。此解决方案创建了额外的抽象,因此我们失去了使用各种数据库的特定SQL功能的优势。
- 抽象必须有助于减少编程复杂性和工作量,同时必须保留每个数据库的优势。
- 在模型中描述关系是错误的。这是一个不必要的抽象和额外的限制,会导致性能下降。
- 永远不要使用查询构建器编写复杂的SQL查询,尤其是使用表连接
与库一起工作
有两种方式可以与数据库交互
- 原始SQL查询
- “行”层
- “模型”层
使用“行”层
您需要创建表类,例如
class UserTable extends PostgreSqlDatabaseTable { public static function getPrimaryKeyName(): string { return 'id'; } public static function getTableName(): string { return 'users'; } }
您需要创建数据库实例,例如
$dsn = 'pgsql:host=172.17.0.1;dbname=mydb'; $pdo = new PDO($dsn, 'postgres', 'mypassword'); $masterDb = new PostgreSqlDatabase($pdo);
现在您可以向数据库执行SQL查询,例如
// Raw SQL $userRows = $masterDb->select('SELECT * FROM users'); // UserTable's method $userTable = new UserTable($masterDb); $userRows = $userTable->getRows([]); // Raw SQL $userRow = $masterDb->select('SELECT * FROM users WHERE id = :user_id', ['user_id' => 100]); // UserTable's method $userTable = new UserTable($masterDb); $userRow = $userTable->getRowById(100); // Raw SQL $row = $masterDb->selectRow('SELECT COUNT(*) cnt FROM users WHERE group_id = :group_id', ['group_id' => 5]); echo $row['cnt']; // UserTable's method $userTable = new UserTable($masterDb); $usersCount = $userTable->getCount(['group_id = ?' => 5]); echo $usersCount;
您可以进行更复杂的SQL查询,例如
// Raw SQL $userRows = $masterDb->select( 'SELECT * FROM users WHERE group_id IN (:group_ids) AND (created_datetime >= :start_time OR created_datetime < finish_time) AND updated_datetime IS NOT NULL ORDER BY created_datetime ASC' ['group_ids' => [5, 6, 12], 'start_time' => '2021-04-01 00:00:00', 'finish_time' => '2021-05-01 00:00:00'] ); // UserTable's method $userTable = new UserTable($masterDb); $userRows = $userTable->getRows( [ 'group_id IN (?)' => [5, 6, 12], 'created_datetime >= ? OR created_datetime < ?' => ['2021-04-01 00:00:00', '2021-05-01 00:00:00'], 'update_datetime IS NOT NULL', ], ['created_datetime ASC'] );
以下技巧建议用于检索另一个表中的相关数据
$userTable = new UserTable($masterDb); $userRows = $userTable->getRows(['created_datetime >= ?' => '2021-04-01 00:00:00']); // Now you want get all related rows from groups table $userGroupIds = array_column($userRows, 'group_id'); $groupTable = new GroupTable($masterDb); $userGroups = $groupTable->getRowsByIds($userGroupIds);
如果想要使用JOIN制作SQL,只需要使用数据库类编写原始SQL!
使用“模型”层
您需要创建模型类,例如
class User { private ?int $id; public ?string $name = null; public string $email; public string $createdDatetime; public ?string $updatedDatetime = null; public function __construct(int $id = null) { $this->id = $id; } public function getId(): ?int { return $this->id; } }
您需要创建映射器类,例如
class UserTableMapper { public static function populateModel(?array $row): ?User { if ($row === null) { return null; } $user = new User($row['id']); $user->name = $row['name']; $user->email = $row['email']; $user->createdDatetime = $row['created_datetime']; $user->updatedDatetime = $row['updated_datetime']; return $user; } public static function fillRowFromModel(User $user): array { return [ 'id' => $user->getId(), 'name' => $user->name, 'email' => $user->email, 'created_datetime' => $user->createdDatetime, 'updated_datetime' => $user->updatedDatetime, ]; } /** * @return User[] */ public static function populateModels(array $rows): array { $models = []; foreach ($rows as $row) { $models[] = static::populateModel($row); } return $models; } }
您需要在UserTable类中添加新方法,例如
class UserTable extends PostgreSqlDatabaseTable { public static function getPrimaryKeyName(): string { return 'id'; } public static function getTableName(): string { return 'users'; } /** * @throws SqlQueryException */ public function getModelById(int $id): ?User { return UserTableMapper::populateModel(parent::getRowById($id)); } /** * @return User[] * @throws SqlQueryException */ public function getModelsByIds(array $ids): array { return UserTableMapper::populateModels(parent::getRowsByIds($ids)); } /** * @throws SqlQueryException */ public function getModel(array $where, ?array $order = null): ?User { return UserTableMapper::populateModel(static::getRow($where, $order)); } /** * @return User[] * @throws SqlQueryException */ public function getModels(array $where, ?array $order = null, ?int $limit = null, ?int $offset = null): array { return UserTableMapper::populateModels(static::getRows($where, $order, $limit, $offset)); } /** * @throws SqlQueryException */ public function save(User $model): User { $row = static::saveRow(UserTableMapper::fillRowFromModel($model)); return UserTableMapper::populateModel($row); } public function saveRow(array $row): array { $date = date('Y-m-d H:i:s'); $row['created_datetime'] = $row['created_datetime'] ?? $date; $row['updated_datetime'] = $date; return parent::saveRow($row); } }
现在您可以使用与“行”层相同的方式查询表,但使用“getModels”方法而不是“getRows”
// Selecting $user = $userTable->getModelById(100); $users = $userTable->getModels(['created_datetime >= ?' => '2021-04-01 00:00:00']); // Saving $unsavedUser = new User(); $unsavedUser->groupId = 10; $unsavedUser->email = 'test@test.local'; // "Save" method returns other instance of User in our example. $user = $userTable->save($unsavedUser);
版权
版权(c)2021 Vladimir Lila。有关详细信息,请参阅LICENSE。