libertyphp/datamapper

LibertyPHP Datamapper。适用于MySQL和PostgreSQL的简单而强大的数据映射器。

1.1 2021-10-01 05:39 UTC

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。