ngyuki / doctrine-table-gateway
为 doctrine-dbal 提供的简单 TableGateway
Requires
- doctrine/dbal: ^2.5
- psr/simple-cache: ^1.0
Requires (Dev)
- cache/doctrine-adapter: ^1.0
- ngyuki/phpunit-functions: ^1.0
This package is auto-updated.
Last update: 2024-09-22 15:32:28 UTC
README
以 doctrine/dbal 为后端的简单表网关。
安装
composer require ngyuki/doctrine-table-gateway:dev-master
使用示例
use ngyuki\DoctrineTableGateway\TableGateway; // Connection のインスタンスとテーブル名をコンストラクタに指定してインスタンスを生成する $t = new TableGateway($connection, 'example'); // find($id) で主キーで 1 件の行を array で返す $t->find(1); // find() は行が見つからない場合は null を返す $t->find(9999); // all() ですべての行のイテレーターが返る $t->all();
作用域
使用 scope()
来限制 find()
或 all()
的结果范围。
// `scope()` でテーブルにスコープを適用する $t->scope('a = 1')->all(); // => WHERE (a = 1) // スコープは連想配列でも指定できる $t->scope(['a' => 1])->all(); // => WHERE (a = 1) // スコープの整数キーの値は SQL の式としてそのまま使用される $t->scope(['a = 1', 'b = 2', 'c' => 3])->all(); // => WHERE (a = 1) AND (b = 2) AND (c = 3) // スコープはチェインできる $t->scope(['a' => 1])->scope(['b' => 0])->all(); // => WHERE (a = 1) AND (b = 2) // チェインや配列で複数指定されたスコープは AND で連結される $t->scope('a = 1 OR b = 2')->scope(['c = 3', 'd' => 4])->all(); // => WHERE (a = 1 OR b = 2) AND (c = 3) AND (d = 4) // スコープを適用したオブジェクトは使いまわすことができる $a = $t->scope('a = 1'); $b = $a->scope('b = 2'); $c = $a->scope('c = 3'); $a->all(); // => WHERE (a = 1) $b->all(); // => WHERE (a = 1) AND (b = 2) $c->all(); // => WHERE (a = 1) AND (c = 3) // orderBy() で並び順を指定する $t->scope('a = 1')->orderBy('b', 'DESC')->all(); // => WHERE (a = 1) ORDER BY b DESC
作用域可以指定一个闭包。可以通过传递一个闭包到作用域中来自由地定制查询,闭包的参数是 Doctrine\DBAL\Query\QueryBuilder
。
$t->scope(function (\Doctrine\DBAL\Query\QueryBuilder $q) { return $q->where('a = 1')->andWhere('b = 2')->orderBy('c', 'desc'); }); // => WHERE (a = 1) AND (b = 1) ORDER BY c DESC
迭代器
all()
方法返回的迭代器定义了一些便利的方法。
// 指定された列値のみのイテレーターを返す $t->all()->asColumn('col'); // 配列なら指定した列値の配列が返る $t->all()->asColumn(['col1', 'col2']); // 指定された列値がキー値となるイテレーターを返す $t->all()->asUnique('col'); // 指定された 2 つの列値がキーと値となるイテレーターを返す $t->all()->asPair('key', 'val'); // 値の方は asColumn と同じように指定できる $t->all()->asPair('key', ['col1', 'col2']); // 複数の列値で多次元連想配列を返す ... `$array[$key1][$key2][$key2] = $val `のような連想配列が返る $t->all()->asGroup(['key1', 'key2', 'key2'], 'val'); // 値の方は asColumn と同じように指定できる $t->all()->asGroup(['key1', 'key2', 'key2'], ['col1', 'col2']); // 値を NULL にすると行がそのまま返る $t->all()->asGroup(['key1', 'key2', 'key2'], null); // イテレーターを配列化する $t->all()->toArray();
例如,当有如下这样的表时,
它们将按以下方式返回。
$t->all()->asColumn('name')->toArray(); // [aaa, bbb, ccc] $t->all()->asColumn(['id', 'age'])->toArray(); // [[1, 16], [2, 24], [3, 32]] $t->all()->asUnique('id')->toArray(); // [ // 1 => [id => 1, name => aaa, age => 16], // 2 => [id => 2, name => bbb, age => 24], // 3 => [id => 3, name => ccc, age => 32], // ] $t->all()->asPair('id', 'name'); // [ // 1 => aaa, // 2 => bbb, // 3 => ccc, // ] $t->all()->asGroup(['id', 'age'], 'name'); // [ // 1 => [ // 16 => aaa // ], // 2 => [ // 24 => bbb, // ], // 3 => [ // 32 => ccc, // ], // ]
INSERT
$t->insert(['a' => 1, 'b' => 2, 'c' => 3]); #=> INSERT INTO ... (a, b, c) VALUES (1, 2, 3)
在 INSERT 中指定不存在的列名将被忽略。
$t->insert(['a' => 1, 'xxx' => 2]); #=> INSERT INTO ... (a) VALUES (1)
可以在作用域的第二个参数中指定 INSERT 的默认值。
$t->scope('a = 1', ['a' => 1])->insert(['b' => 2, 'c' => 3]); #=> INSERT INTO ... (a, b, c) VALUES (1, 2, 3)
如果省略了作用域的第二个参数,则仅使用第一个参数的 key => value
格式的值作为默认值。
$t->scope('a = 1', ['b' => 2])->insert(['c' => 3]); #=> INSERT INTO ... (b, c) VALUES (2, 3)
UPDATE/DELETE
使用 update($data)
指定的数据来更新作用域中的所有行。
$t->scope('a = 1')->update(['b' => 2, 'c' => 3]); #=> UPDATE ... SET b = 2, c = 3 WHERE a = 1
如果 update($data)
中指定了不存在的列,它将被忽略。
$t->scope('a = 1')->update(['b' => 2, 'xxx' => 9]); #=> UPDATE ... SET b = 2 WHERE a = 1
使用 update($data)
来删除作用域中的所有行。
$t->scope('a = 1')->delete(); #=> DELETE FROM ... WHERE a = 1
当需要指定主键时,请使用 by($id)
应用作用域。
$t->by(1)->update(['a' => 1, 'b' => 2, 'c' => 3]); #=> UPDATE ... SET a = 1, b = 2, c = 3 WHERE id = 1 $t->by(1)->delete(); #=> DELETE FROM ... WHERE id = 1
如果没有应用作用域,则所有行都将被考虑。
$t->update(['a' => 1, 'b' => 2, 'c' => 3]); #=> UPDATE ... SET a = 1, b = 2, c = 3 $t->delete(); #=> DELETE FROM ...
元数据缓存
默认情况下,TableGateway 每次实例化时都会从数据库中获取表定义的元数据,但可以通过以下方式使用缓存:
use ngyuki\DoctrineTableGateway\TableGateway; use ngyuki\DoctrineTableGateway\Metadata; $t = new TableGateway($connection, 't_user', new Metadata($connection, $cache));
$cache
中指定了实现了 PSR-16 的 Psr\SimpleCache\CacheInterface
的对象。
如果使用 doctrine 的缓存,可以使用 cache/doctrine-adapter。
composer require cache/doctrine-adapter
use ngyuki\DoctrineTableGateway\TableGateway; use ngyuki\DoctrineTableGateway\Metadata; use Doctrine\Common\Cache\ApcuCache; use Cache\Adapter\Doctrine\DoctrineCachePool; $cache = new DoctrineCachePool(new ApcuCache()); $t = new TableGateway($connection, 't_user', new Metadata($connection, $cache));
表连接
不能这样做。
对于 OneToMany/ManyToOne/ManyToMany 这样的关系,如何遍历表不是可以机械判断的。
如果真的需要这样做,可以将闭包传递给 scope()
,并对查询构建器进行一些操作。
未记录文档
README.md 中未记录的功能
- 查询
- 执行指定的 SQL 并获取结果集
- 事务性
- 在事务中执行回调函数
- ExpressionBuilder
- 作用域的表达式变得更丰富了