rougin / windstorm
一个可链式、可表达和互操作的 SQL 查询构建器。
Requires
- php: >=5.3.0
- doctrine/dbal: ~2.5
Requires (Dev)
- doctrine/orm: ~2.4
- illuminate/database: >=4.1
- phpunit/phpunit: ~4.2|~5.7
- scrutinizer/ocular: ~1.1
This package is auto-updated.
Last update: 2024-09-25 08:18:43 UTC
README
Windstorm 是一个基于 Doctrine 的 数据库抽象层 (DBAL) 的可表达 SQL 查询构建器。它具有与 DBAL 查询构建器相同的功能,但不同之处在于它不需要 Doctrine\DBAL\Connection 实例。它的目标是成为处理 SQL 查询构建器和 对象关系映射器 (ORM) 的单一接口。Windstorm 目前为 Doctrine(通过 DBAL)和 Eloquent 提供查询实现。
原因
我试图将 Doctrine 和 Eloquent 统一成一个单一接口,以便它们可以互换。不幸的是,由于不同的核心设计模式(Doctrine 使用 数据映射模式,而 Eloquent 使用 活动记录模式),实现是不可能的。后来我意识到,两者共同的一点是它们的查询构建器,这也在所有现有的 ORM 包和 SQL 查询构建器中很常见。
安装
通过 Composer 安装 Windstorm
$ composer require rougin/windstorm:dev-master
基本用法
配置
由于查询构建器默认不需要 Doctrine\DBAL\Connection,因此需要指定一个平台
use Doctrine\DBAL\Platforms\AbstractPlatform; use Rougin\Windstorm\Doctrine\Builder; use Rougin\Windstorm\Doctrine\Query; // $platform instanceof AbstractPlatform $query = new Query(new Builder($platform));
支持的平台列表(Doctrine DBAL):https://www.doctrine-project.org/projects/doctrine-dbal/en/2.8/reference/platforms.html
使用 Connection 实例
如果平台需要来自数据库连接,请使用 Connection::createQueryBuilder 方法
use Doctrine\DBAL\Connection; use Rougin\Windstorm\Doctrine\Query; // $connection instanceof Connection $query = new Query($connection->createQueryBuilder());
有关获取连接的文档: https://www.doctrine-project.org/projects/doctrine-dbal/en/2.8/reference/configuration.html
查询构建器
查询构建器语法与编写 SQL 查询时的语法类似
// $query instanceof Rougin\Windstorm\QueryInterface $query = $query ->select(array('u.id', 'u.name')) ->from('users', 'u') ->where('name')->like('%winds%') ->orderBy('created_at')->descending(); // SELECT u.id, u.name FROM users u WHERE u.name LIKE :u_name ORDER BY u.created_at DESC $sql = $query->sql(); // array(':u_name' => '%winds%') $bindings = $query->bindings();
返回结果
要从定义的查询中返回结果,必须在 ResultInterface 中实现一个实例。
// $connection instanceof Doctrine\DBAL\Connection // $query instanceof Rougin\Windstorm\QueryInterface use Rougin\Windstorm\Doctrine\Result; $result = new Result($connection); $query = $query->select(array('u.*')); $query = $query->from('users'); $result = $result->execute($query); var_dump((array) $result->items());
array(3) {
[0] =>
array(4) {
'id' =>
string(1) "1"
'name' =>
string(9) "Windstorm"
'created_at' =>
string(19) "2018-10-15 23:06:28"
'updated_at' =>
NULL
}
[1] =>
array(4) {
'id' =>
string(1) "2"
'name' =>
string(11) "SQL Builder"
'created_at' =>
string(19) "2018-10-15 23:09:47"
'updated_at' =>
NULL
}
[2] =>
array(4) {
'id' =>
string(1) "3"
'name' =>
string(12) "Rougin Gutib"
'created_at' =>
string(19) "2018-10-15 23:14:45"
'updated_at' =>
NULL
}
}
QueryRepository 和突变
QueryRepository 实例是一个特殊类,它将通过使用突变(在 MutatorInterface 中实现)来通过突变修改 QueryInterface。使用这种方法将条件分离到类中,而不是在仓库中定义方法。
namespace Acme\Mutators; use Rougin\Windstorm\Mutators\ReturnEntity; class ReturnUser extends ReturnEntity { protected $table = 'users'; }
可扩展的可用突变
CreateEntity(array $data)- 生成INSERT INTO查询DeleteEntity(integer $id)- 生成DELETE FROM查询ReturnEntities($limit, $offset)- 生成带有限制和偏移的SELECT查询ReturnEntity(integer $id)- 生成SELECT查询(在ResultInterface中使用first)UpdateEntity($id, array $data)- 生成UPDATE查询
// $query instanceof Rougin\Windstorm\QueryInterface; // $result instanceof Rougin\Windstorm\ResultInterface; use Acme\Mutators\ReturnUser; $query = $query->select(['*'])->from('users'); $query = new QueryRepository($query, $result); $query = $query->mutate(new ReturnUser(1)); var_dump($query->first());
array(4) {
'id' =>
string(1) "1"
'name' =>
string(9) "Windstorm"
'created_at' =>
string(19) "2018-10-15 23:06:28"
'updated_at' =>
NULL
}
要将结果映射到类中,请实现一个 MapperInterface 中的映射器
namespace Acme\Mappers; use Acme\Models\User; class UserMapper implements MapperInterface { public function map($data) { return new User($data['id'], $data['name']); } }
// $query instanceof Rougin\Windstorm\QueryRepository; use Acme\Mappers\UserMapper; $query->mapper(new UserMapper); var_dump($query->first());
class Acme\Models\User#11 (2) { protected $id => string(1) "1" protected $name => string(6) "Windstorm" }
如果没有实现从 MapperInterface 继承的类,则将从 ResultInterface 返回数据
混合查询
在执行SQL查询时,在ResultInterface中只允许执行一个QueryInterface。但存在需要先执行一个查询实例,然后使用前一个查询的结果执行另一个查询实例的场景。为了解决这个问题,可以实现一个MixedInterface,它仍然是一个QueryInterface,但能够添加子查询(在ChildInterface中实现)。
// $users instanceof \Rougin\Windstorm\QueryInterface // $posts instanceof \Rougin\Windstorm\QueryInterface use Rougin\Windstorm\Relation\Mixed; use Rougin\Windstorm\Relation\Child; $mixed = new Mixed($users, 'id'); $child = new Child($child, 'id', 'user_id'); $mixed->add($child, 'posts'); // SELECT u.id, u.name FROM users u echo $mixed->sql(); $child = current($mixed->all()); // SELECT p.id, p.title, p.body, p.user_id FROM posts p echo $child->sql();
致谢
许可证
MIT许可证(MIT)。更多信息请参阅LICENSE。