kaizencoders / wp-fluent
一个轻量级、表达式的WordPress数据库查询构建器,也可以称之为数据库抽象层。WP Fluent使用相同的**wpdb**实例,并使用统一的API处理查询清理、表前缀以及其他许多事情。
Requires
- php: >=5.6
This package is auto-updated.
Last update: 2024-09-29 05:56:34 UTC
README
一个轻量级、表达式的WordPress数据库查询构建器,也可以称之为数据库抽象层。WP Fluent使用相同的wpdb实例,并使用统一的API处理查询清理、表前缀以及其他许多事情。
它具有一些高级功能,如
- 查询事件
- 嵌套条件
- 子查询
- 嵌套查询
语法与Laravel的查询构建器非常相似。
示例
// You can use the global wpFluent() function $user = wpFluent()->table('users')->find(1); // Or, create a connection using $wpdb, only once. global $wpdb; new \WpFluent\Connection($wpdb, ['prefix' => $wpdb->prefix], 'DB');
简单查询
以下查询返回id = 3的行,如果没有行则返回null
。
$user = DB::table('users')->find(3);
完整查询
$query = DB::table('users')->where('display_name', 'LIKE', '%admin%'); // Get result $query->get();
查询事件
以下代码之后,每次在posts
表上执行选择查询时,都会添加此where条件,因此草稿帖子不会显示。
DB::registerEvent('before-select', 'posts', function ($qb) { $qb->where('psot_status', '!=', 'draft'); });
以下有许多高级选项进行了文档说明。准备好了吗?让我们开始安装。
完整使用API
目录
- 连接
- 查询
- 选择
- where
- 分组by和排序by
- having
- 限制和偏移
- 连接
- 原始查询
- 插入
- 更新
- 删除
- 事务
- 获取构建的查询
- 子查询和嵌套查询
- 获取PDO实例
- 以指定类的对象形式获取结果
- 查询事件
连接
WP Fluent支持多个数据库连接,但您一次只能使用一个别名。只需在连接时传递全局wpdb和必要的配置即可。
// Get the global wpdb instance. global $wpdb; new \WpFluent\Connection($wpdb, ['prefix' => $wpdb->prefix], 'DB'); // Run query $query = DB::table('my_table')->where('name', '=', 'admin'); // Or, simply use the global wpFluent() function. // It handles all the ncessary initial setup. wpFluent()->table('my_table')->where('name', '=', 'admin');
别名
当您创建连接时
new \WpFluent\Connection($wpdb, ['prefix' => $wpdb->prefix], 'MyAlias');
MyAlias
是要使用的类别名的名称,例如MyAlias::table(...)
您可以使用任何名称(包括命名空间,例如MyNamespace\\MyClass
),或者如果您不需要别名,也可以跳过它。别名可以让您轻松地在应用程序中访问QueryBuilder类。
当不使用别名时,您可以单独实例化QueryBuilder处理器,这对于依赖注入和测试非常有帮助。
$connection = new \WpFluent\Connection($wpdb, ['prefix' => $wpdb->prefix]); $db = new \WpFluent\QueryBuilder\QueryBuilderHandler($connection); $query = $db->table('my_table')->where('name', '=', 'admin'); var_dump($query->get());
查询
除了原始的query()
之外,您必须在每个查询之前使用table()
方法。要从多个表中选择,只需传递一个数组。
DB::table(array('mytable1', 'mytable2'));
轻松获取
以下查询返回id = 3的第一行,如果没有行则返回null
。
$row = DB::table('my_table')->find(3);
可以像这样访问行:echo $row->name
。如果您的字段名不是id
,则将字段名作为第二个参数传递DB::table('my_table')->find(3, 'person_id');
以下查询返回所有name = 'Frost'的行,如果没有行则返回null
。
$result = DB::table('my_table')->findAll('name', 'admin');
选择
$query = DB::table('my_table')->select('*');
多选
->select(array('mytable.myfield1', 'mytable.myfield2', 'another_table.myfield3'));
多次使用select方法select('a')->select('b')
也会选择a
和b
。如果您想要进行条件选择(在PHP的if
中),这可能会很有用。
选择唯一
->selectDistinct(array('mytable.myfield1', 'mytable.myfield2'));
获取全部
返回一个数组。
$query = DB::table('my_table')->where('name', '=', 'admin'); $result = $query->get();
您可以像这样遍历它
foreach ($result as $row) { echo $row->name; }
获取第一行
$query = DB::table('my_table')->where('name', '=', 'admin'); $row = $query->first();
返回第一行,或者如果没有记录则返回null
。使用此方法,您还可以确保记录是否存在。可以像这样访问它:$row->name
获取行数
$query = DB::table('my_table')->where('name', '=', 'admin'); $query->count();
where
基本语法是 (字段名, 操作符, 值)
,如果你提供两个参数,则假定使用 =
操作符。因此,where('name', 'admin')
和 where('name', '=', 'admin')
是相同的。
DB::table('my_table') ->where('name', '=', 'admin') ->whereNot('age', '>', 25) ->orWhere('type', '=', 'admin') ->orWhereNot('description', 'LIKE', '%query%');
where in
DB::table('my_table') ->whereIn('name', array('rabindranath', 'najrul')) ->orWhereIn('name', array('homer', 'frost')); DB::table('my_table') ->whereNotIn('name', array('homer', 'frost')) ->orWhereNotIn('name', array('rabindranath', 'najrul'));
where between
DB::table('my_table') ->whereBetween('id', 10, 100) ->orWhereBetween('status', 5, 8);
where null
DB::table('my_table') ->whereNull('modified') ->orWhereNull('field2') ->whereNotNull('field3') ->orWhereNotNull('field4');
分组where
有时查询变得复杂,需要分组条件,例如 WHERE age = 10 and (name like '%frost%' or description LIKE '%najrul%')
WP Fluent 允许你这样做,你可以嵌套任意数量的闭包,如下所示。
DB::table('my_table') ->where('my_table.age', 10) ->where(function ($q) { $q->where('name', 'LIKE', '%najrul%'); // You can provide a closure on these wheres too, to nest further. $q->orWhere('description', 'LIKE', '%frost%'); });
分组by和排序by
$query = DB::table('my_table')->groupBy('age')->orderBy('created_at', 'ASC');
多重分组
->groupBy(array('mytable.myfield1', 'mytable.myfield2', 'another_table.myfield3')); ->orderBy(array('mytable.myfield1', 'mytable.myfield2', 'another_table.myfield3'));
使用 groupBy()
或 orderBy()
方法多次 groupBy('a')->groupBy('b')
也会先按 a
分组,然后按 b
分组。如果你想在 PHP if
中进行条件分组,这很有用。同样适用于 orderBy()
。
having
->having('total_count', '>', 2) ->orHaving('type', '=', 'admin');
限制和偏移
->limit(30); ->offset(10);
连接
DB::table('my_table') ->join('another_table', 'another_table.person_id', '=', 'my_table.id')
可用方法:
- join() 或 innerJoin
- leftJoin()
- rightJoin()
如果你需要 FULL OUTER
连接或任何其他连接,只需将连接作为 join
方法的第五个参数传递。
->join('another_table', 'another_table.person_id', '=', 'my_table.id', 'FULL OUTER')
多个连接条件
如果你需要多个条件来连接一个表,则将闭包作为第二个参数传递。
->join('another_table', function ($table) { $table->on('another_table.person_id', '=', 'my_table.id'); $table->on('another_table.person_id2', '=', 'my_table.id2'); $table->orOn('another_table.age', '>', DB::raw(1)); })
原始查询
如果你需要,始终可以使用原始查询:
$query = DB::query('select * from cb_my_table where age = 12'); var_dump($query->get());
你也可以传递你的绑定
DB::query('select * from cb_my_table where age = ? and name = ?', array(10, 'najrul'));
原始表达式
当你用 raw()
方法包裹一个表达式时,WP Fluent 不会尝试清理这些内容。
DB::table('my_table') ->select(DB::raw('count(cb_my_table.id) as tot')) ->where('value', '=', 'Frost') ->where(DB::raw('DATE(?)', 'now'))
注意:通过 query()
方法运行的查询直到你通过绑定传递所有值之前都不会清理。通过 raw()
方法运行的查询也不会清理,你必须自己进行清理。当然,这些也不会添加表前缀,但你可以使用 addTablePrefix()
方法。
插入
$data = [ 'name' => 'Najrul', 'description' => 'Famous Bengali poet.' ]; $insertId = DB::table('my_table')->insert($data);
insert()
方法返回插入 ID。
批量插入
$data = array( [ 'name' => 'Najrul', 'description' => 'Famous Bengali poet.' ], [ 'name' => 'Rabindranath', 'description' => 'Nobel winning Bengali poet.' ], ); $insertIds = DB::table('my_table')->insert($data);
在批量插入的情况下,它将返回一个包含插入 ID 的数组。
带有ON DUPLICATE KEY语句的插入
$data = [ 'name' => 'Najrul', 'counter' => 1 ]; $dataUpdate = [ 'name' => 'Najrul', 'counter' => 2 ]; $insertId = DB::table('my_table')->onDuplicateKeyUpdate($dataUpdate)->insert($data);
更新
$data = [ 'name' => 'Najrul', 'description' => 'Famous Bengali poet.' ]; DB::table('my_table')->where('id', 5)->update($data);
它将 name
字段更新为 Najrul
,并将 description
字段更新为 著名的孟加拉诗人。
其中 id
= 5
。
删除
DB::table('my_table')->where('id', '>', 5)->delete();
它将删除所有 id
大于 5
的行。
事务
WP Fluent 具有运行数据库 "事务" 的能力,在这种事务中,所有数据库更改在提交之前都不会保存。这样,如果发生错误或与预期不同,数据库更改将不会保存,也不会进行任何更改。
这是一个基本事务的示例
DB::transaction(function ($qb) { $qb->table('my_table')->insert([ 'name' => 'Test', 'url' => 'example.com' ]); $qb->table('my_table')->insert([ 'name' => 'Test2', 'url' => 'example.com' ]); });
如果这会导致任何错误(如重复名称或其他此类错误),则两个数据集都不会出现在数据库中。如果没有,更改将成功保存。
如果你希望手动提交或回滚更改,可以使用相应的 commit()
和 rollback()
方法。
DB::transaction(function ($qb) { $qb->table('my_table')->insert(array(/* data... */)); $qb->commit(); // to commit the changes (data would be saved) $qb->rollback(); // to rollback the changes (data would be rejected) });
获取构建的查询
有时你可能需要获取查询字符串,这是可能的。
$query = DB::table('my_table')->where('id', '=', 3); $queryObj = $query->getQuery();
getQuery()
将返回一个查询对象,你可以从其中获取 SQL、绑定或原始 SQL。
$queryObj->getSql(); // Returns: SELECT * FROM my_table where `id` = ?
$queryObj->getBindings(); // Returns: array(3)
$queryObj->getRawSql(); // Returns: SELECT * FROM my_table where `id` = 3
子查询和嵌套查询
很少,但你可能需要运行子查询或嵌套查询。WP Fluent 足够强大,可以为你做这件事。你可以创建不同的查询对象并使用 DB::subQuery()
方法。
$subQuery = DB::table('person_details')->select('details')->where('person_id', '=', 3); $query = DB::table('my_table') ->select('my_table.*') ->select(DB::subQuery($subQuery, 'table_alias1')); $nestedQuery = DB::table(DB::subQuery($query, 'table_alias2'))->select('*'); $nestedQuery->get();
这将生成如下查询
SELECT * FROM (SELECT `cb_my_table`.*, (SELECT `details` FROM `cb_person_details` WHERE `person_id` = 3) as table_alias1 FROM `cb_my_table`) as table_alias2
注意:WP Fluent 不对子查询和嵌套查询使用绑定。
获取 wpdb 实例
如果你需要获取 wpdb 实例,你可以这样做。
DB::db();
查询事件
WP Fluent 提供强大的查询事件来增强你的应用程序。这些事件类似于数据库触发器,当事件发生时可以执行某些操作。例如,你可以挂钩表的 after-delete
事件并从另一个表中删除相关数据。
可用事件
- before-select
- after-select
- before-insert
- after-insert
- before-update
- after-update
- before-delete
- after-delete
注册事件
DB::registerEvent('before-select', 'users', function ($qb) { $qb->where('status', '!=', 'banned'); });
现在每次在 users
表上执行选择查询时,都会添加这个 where 条件,这样被禁用的用户就不会获得访问权限。
语法是 registerEvent('事件类型', '表名', 闭包中的操作)
。
如果你想在 任何表被查询时 执行事件,提供 ':any'
作为表名。
其他示例
在将数据插入到 my_table
后,详情将被插入到另一个表中
DB::registerEvent('after-insert', 'my_table', function ($queryBuilder, $insertId) { $data = array('person_id' => $insertId, 'details' => 'Meh', 'age' => 5); $queryBuilder->table('person_details')->insert($data); });
每当数据被插入到 person_details
表时,设置时间戳字段 created_at
,这样我们就不必在所有地方都指定它
DB::registerEvent('after-insert', 'person_details', function ($queryBuilder, $insertId) { $queryBuilder->table('person_details') ->where('id', $insertId) ->update([ 'created_at' => date('Y-m-d H:i:s') ]); });
从 my_table
删除后,删除关系
DB::registerEvent('after-delete', 'my_table', function ($queryBuilder, $queryObject) { $bindings = $queryObject->getBindings(); $queryBuilder->table('person_details')->where('person_id', $binding[0])->delete(); });
WP Fluent 将查询构建器的当前实例作为您闭包的第一个参数传递,因此您可以使用此对象构建查询,您可以像通常的查询构建器(DB
)一样做任何事情。
如果从 before-*
查询处理程序返回的不是 null
,则值将是执行的结果,并且数据库实际上不会被查询(因此,相应的 after-*
处理程序也不会被调用)。
只有在 after-*
事件中您才会得到三个参数:第一个是查询构建器,第三个是执行时间作为浮点数,第二个是变化的。
- 在
after-select
中,您将得到从select
获得的结果。 - 在
after-insert
中,您将得到插入 id(或在批量插入的情况下是 id 的数组)。 - 在
after-delete
中,您将得到查询对象(与从getQuery()
获得的对象相同),您可以从其中获取 SQL 和绑定。 - 在
after-update
中,您将得到类似于after-delete
的 查询对象。
删除事件
DB::removeEvent('event-name', 'table-name');
一些用例
以下是一些查询事件非常有用的案例。
- 限制被禁用的用户。
- 只获取
deleted = 0
记录。 - 实现所有查询的缓存。
- 在每次条目后触发用户通知。
- 在删除查询后删除关系数据。
- 在插入查询后插入关系数据。
- 在每个更新查询后保留修改记录。
- 在每个条目后添加/编辑 created_at 和 updated_at 数据。
注意
- 查询事件是递归的,例如,在向
table_a
插入后,您的事件会插入到table_b
中,现在您可以在table_b
上注册另一个事件,该事件会插入到table_c
中。 - 当然,查询事件不与原始查询一起工作。
- 这是从出色的 @usmanhalalit vai 的 Pixie 分支出来,并修改为支持 WordPress。