webrium / foxdb
Foxdb查询构建器
Requires
- php: ^8
Requires (Dev)
- phpunit/phpunit: ^9
- webrium/core: dev-master
README
属性
- ✔️ 资源使用低
- ✔️ 轻量级且快速
- ✔️ 与Laravel查询构建器语法相似
- ✔️ 易于配置和使用
Foxdb查询构建器使用PDO参数绑定来保护您的应用程序免受SQL注入攻击。无需清理或净化传递给查询构建器的查询绑定字符串。
通过Composer安装
composer require webrium\foxdb
-
选择
添加连接配置
use Foxdb\DB; use Foxdb\Config; DB::addConnection('main', [ 'host'=>'localhost', 'port'=>'3306', 'database'=>'test', 'username'=>'root', 'password'=>'1234', 'charset'=>Config::UTF8, 'collation'=>Config::UTF8_GENERAL_CI, 'fetch'=>Config::FETCH_CLASS ]);
'main'
是连接配置的默认名称
从表中检索所有行
您可以使用DB外观类提供的table
方法开始查询。该方法返回给定表的流畅查询构建器实例,允许您将更多约束链接到查询上,然后最终使用get方法检索查询结果
use Foxdb\DB; $users = DB::table('users')->get(); foreach ($users as $user) { echo $user->name; }
从表中检索单行/列
如果您只需从数据库表中检索单行,您可以使用DB外观类的first
方法。该方法将返回一个stdClass对象
$user = DB::table('users')->where('name', 'Jack')->first(); return $user->email;
如果您不需要整行,您可以使用value
方法从记录中提取单个值。此方法将直接返回列的值
$email = DB::table('users')->where('name', 'John')->value('email');
要按其id
列的值检索单行,请使用find
方法
$user = DB::table('users')->find(3);
find
方法和first
方法之间的区别在于,如果存在结果,first
方法以stdClass形式返回结果,而find
方法以Model
形式返回结果,这为我们提供了更多功能。(如果值不存在,两种方法都返回false。)
🆕 从版本3开始,查询可用于查找
$user = User::find(3); if($user){ $user->name = 'Tom'; $user->save(); // update name } $user = User::where('phone', '09999999999')->find(); if($user){ $user->phone = '09999999998'; $user->save(); // update user phone number }
检索列值列表
您可以使用pluck
方法。在这个例子中,我们将检索用户标题的集合
use Foxdb\DB; $titles = DB::table('users')->pluck('title'); foreach ($titles as $title) { echo $title; }
您可以通过向pluck方法提供第二个参数来指定结果集合应使用的列作为其键
$titles = DB::table('users')->pluck('title', 'name'); foreach ($titles as $name => $title) { echo $title; }
分块结果
如果您需要处理数千条数据库记录,请考虑使用DB外观类提供的chunk
方法。此方法一次检索一小块结果,并将每个块喂入闭包进行处理。例如,让我们以每次100条记录的块来检索整个用户表
use Foxdb\DB; DB::table('users')->orderBy('id')->chunk(100, function ($users) { foreach ($users as $user) { // } });
您可以通过从闭包中返回false来停止进一步处理块
DB::table('users')->orderBy('id')->chunk(100, function ($users) { // Process the records... return false; });
您可以使用each
方法。
use Foxdb\DB; DB::table('users')->orderBy('id')->each(function ($user) { // });
分页
FoxDB已创建一种简单的分页方法。在下面的示例中,结果数限制为10条记录,您可以通过更改页码来获取信息。
$page = 1; $list = DB::table('posts') ->is('active') ->paginate(10, $page);
其输出是一个包含以下属性的stdClass对象
$list->total; // The total number of rows $list->count; // The number of rows received on the current page $list->per_page; // The number of rows to display on each page $list->prev_page; // Previous page number. If not available, its value is false $list->next_page; // next page number. If not available, its value is false $list->current_page; // Current page number $list->data; // List of data rows
聚合
查询构建器还提供了多种方法来检索汇总值,如 count
(计数)、max
(最大值)、min
(最小值)、avg
(平均值)和 sum
(总和)。您可以在构建查询后调用这些方法中的任何一个
use Foxdb\DB; $users = DB::table('users')->count(); $price = DB::table('orders')->max('price');
当然,您可以将这些方法与其他子句结合使用,以微调汇总值的计算方式
$price = DB::table('orders') ->where('finalized', 1) ->avg('price');
确定是否存在记录
您可以使用 exists 和 doesntExist 方法,而不是使用 count 方法来确定是否存在符合查询约束的记录
if (DB::table('orders')->where('finalized', 1)->exists()) { // ... } if (DB::table('orders')->where('finalized', 1)->doesntExist()) { // ... }
选择语句
指定选择子句
您不一定总是想从数据库表中选取所有列。使用 select
方法,您可以指定查询的定制 "select" 子句
use Foxdb\DB; $users = DB::table('users') ->select('name', 'email as user_email') ->get(); // Or you can send as an array $users = DB::table('users') ->select(['name', 'email as user_email']) ->get();
但有一种更现代的方法。您可以参考以下示例
$users = DB::table('users') ->select(function($query){ $query->field('name'); $query->field('email')->as('user_email'); }) ->get();
原始表达式
有时您可能需要在查询中插入一个任意的字符串。要创建一个原始字符串表达式,您可以使用由 DB
外观提供的 raw
方法
$users = DB::table('users') ->select(DB::raw('count(*) as user_count, status')) ->where('status', '<>', 1) ->groupBy('status') ->get();
以下是如何在原始字符串中使用参数的示例
DB::raw('count(?)', ['id'])
⚠️ 原始语句将被注入到查询中作为字符串,因此您应非常小心,以避免创建 SQL 注入漏洞。
我们的建议
但为了这个目的,使用以下方法来避免 SQL 注入
攻击会更好
$users = DB::table('users') ->select(function($query){ $query->count('*')->as('user_count') $query->field('status'); }) ->get();
在这个结构中,您可以访问 field
、count
、sum
、avg
、min
、max
、all
、as
方法。
原始方法
您还可以使用以下方法将原始表达式插入到查询的各个部分。请记住,Foxdb 不能保证使用原始表达式的任何查询都受到 SQL 注入漏洞的保护。
whereRaw / orWhereRaw
whereRaw 和 orWhereRaw 方法可用于将原始 "where" 子句注入到查询中。这些方法接受一个可选的绑定数组作为它们的第二个参数
$orders = DB::table('orders') ->whereRaw('price > IF(state = "TX", ?, 100)', [200]) ->get();
havingRaw / orHavingRaw
havingRaw 和 orHavingRaw 方法可用于将原始字符串作为 "having" 子句的值。这些方法接受一个可选的绑定数组作为它们的第二个参数
$orders = DB::table('orders') ->select('department', DB::raw('SUM(price) as total_sales')) ->groupBy('department') ->havingRaw('SUM(price) > ?', [2500]) ->get();
内部连接子句
查询构建器还可以用于向查询添加连接子句。要执行基本的 "inner join",您可以使用查询构建器实例上的 join 方法。传递给 join 方法的第一个参数是需要连接的表的名称,其余参数指定连接的列约束。您甚至可以在单个查询中连接多个表
use Foxdb\DB; $users = DB::table('users') ->join('contacts', 'users.id', '=', 'contacts.user_id') ->join('orders', 'users.id', '=', 'orders.user_id') ->select('users.*', 'contacts.phone', 'orders.price') ->get();
在 Foxdb 中,您可以更轻松地完成此操作
$users = DB::table('users') ->select('users.*', 'orders.price') ->join('orders.user_id', 'users.id') ->get();
在这个结构中,您输入要连接的表的名称及其外键(例如 'orders.user_id'
),然后是主键(例如 'user.id'
)。
左连接 / 右连接子句
如果您想执行 "left join" 或 "right join" 而不是 "inner join",请使用 leftJoin 或 rightJoin 方法。这些方法与 join 方法的签名相同
$users = DB::table('users') ->leftJoin('posts', 'users.id', '=', 'posts.user_id') ->get();
$users = DB::table('users') ->rightJoin('posts', 'users.id', '=', 'posts.user_id') ->get();
交叉连接子句
您可以使用 crossJoin 方法执行 "cross join"。交叉连接生成第一个表和连接表的笛卡尔积
$sizes = DB::table('sizes') ->crossJoin('colors') ->get();
WHERE子句
您可以使用查询构建器的 where 方法向查询添加 "where" 子句。where 方法的最基本调用需要三个参数。第一个参数是列的名称。第二个参数是运算符,可以是数据库支持的任何运算符。第三个参数是要与列的值进行比较的值。
例如,以下查询检索投票列值为 100 且年龄列值大于 35 的用户
$users = DB::table('users') ->where('votes', '=', 100) ->where('age', '>', 35) ->get();
为了方便起见,如果您想验证一个列是否等于给定的值,您可以将该值作为 where 方法的第二个参数传递。Foxdb 将假设您想使用 = 运算符
$users = DB::table('users')->where('votes', 100)->get();
如前所述,您可以使用数据库系统支持的任何运算符
$users = DB::table('users') ->where('votes', '>=', 100) ->get();
$users = DB::table('users') ->where('votes', '<>', 100) ->get();
$users = DB::table('users') ->where('name', 'like', 'T%') ->get();
或Where子句
当链式调用查询构建器的where方法时,"where"子句将使用and运算符连接起来。然而,您可以使用orElse方法使用or运算符将子句连接到查询中。orElse方法接受与where方法相同的参数
$users = DB::table('users') ->where('votes', '>', 100) ->orWhere('name', 'John') ->get();
如果需要将"or"条件分组在括号内,您可以将闭包作为orElse方法的第一参数传递
$users = DB::table('users') ->where('votes', '>', 100) ->orWhere(function($query) { $query->where('name', 'Abigail') ->where('votes', '>', 50); }) ->get();
上面的示例将生成以下SQL
select * from users where votes > 100 or (name = 'Abigail' and votes > 50)
Where Not子句
可以使用whereNot
和orWhereNot
方法来否定给定的查询约束组。例如,以下查询排除了正在特价或价格低于十的产品
$products = DB::table('products') ->whereNot(function ($query) { $query->where('clearance', true) ->orWhere('price', '<', 10); }) ->get();
其他Where子句
whereBetween / orWhereBetween
whereBetween
方法验证列的值是否介于两个值之间
$users = DB::table('users') ->whereBetween('votes', [1, 100]) ->get();
whereNotBetween / orWhereNotBetween
whereNotBetween
方法验证列的值是否在两个值之外
$users = DB::table('users') ->whereNotBetween('votes', [1, 100]) ->get();
whereIn / whereNotIn / orWhereIn / orWhereNotIn
whereIn
方法验证给定列的值是否包含在给定的数组中
$users = DB::table('users') ->whereIn('id', [1, 2, 3]) ->get();
whereNotIn
方法验证给定列的值是否不在给定的数组中
$users = DB::table('users') ->whereNotIn('id', [1, 2, 3]) ->get();
whereNull / whereNotNull / orWhereNull / orWhereNotNull
whereNull
方法验证给定列的值是否为NULL
$users = DB::table('users') ->whereNull('updated_at') ->get();
whereNotNull
方法验证列的值是否不为NULL
$users = DB::table('users') ->whereNotNull('updated_at') ->get();
whereDate / whereMonth / whereDay / whereYear / whereTime
whereDate
方法可以用来比较列的值与日期
$users = DB::table('users') ->whereDate('created_at', '2016-12-31') ->get();
whereMonth
方法可以用来比较列的值与特定的月份
$users = DB::table('users') ->whereMonth('created_at', '12') ->get();
whereDay
方法可以用来比较列的值与特定的月份中的某一天
$users = DB::table('users') ->whereDay('created_at', '31') ->get();
whereYear
方法可以用来比较列的值与特定的年份
$users = DB::table('users') ->whereYear('created_at', '2016') ->get();
whereTime
方法可以用来比较列的值与特定的时间
$users = DB::table('users') ->whereTime('created_at', '=', '11:20:45') ->get();
whereColumn / orWhereColumn
whereColumn
方法可以用来验证两个列是否相等
$users = DB::table('users') ->whereColumn('first_name', 'last_name') ->get();
您还可以向whereColumn
方法传递一个比较运算符
$users = DB::table('users') ->whereColumn('updated_at', '>', 'created_at') ->get();
排序、分组、限制和偏移
排序
orderBy方法
orderBy
方法允许您根据给定的列对查询结果进行排序。orderBy方法接受的第一个参数应该是您希望排序的列,而第二个参数确定排序的方向,可以是asc或desc
$users = DB::table('users') ->orderBy('name', 'desc') ->get();
要按多个列排序,您可以多次调用orderBy方法
$users = DB::table('users') ->orderBy('name', 'desc') ->orderBy('email', 'asc') ->get();
最新和最早方法
latest
和oldest
方法允许您轻松地按日期对结果进行排序。默认情况下,结果将按表的created_at
列排序。或者,您也可以传递您希望排序的列名
$user = DB::table('users') ->latest() ->first();
随机排序
inRandomOrder方法可以用来随机排序查询结果。例如,您可以使用此方法获取一个随机用户
$randomUser = DB::table('users') ->inRandomOrder() ->first();
分组
groupBy和having方法
正如您所预期的,groupBy和having方法可以用来对查询结果进行分组。having方法的签名与where方法类似
$users = DB::table('users') ->groupBy('account_id') ->having('account_id', '>', 100) ->get();
您可以向groupBy方法传递多个参数以按多个列进行分组
$users = DB::table('users') ->groupBy('first_name', 'status') ->having('account_id', '>', 100) ->get();
要构建更高级的having语句,请参阅havingRaw方法。
限制和偏移量
skip和take方法
您可以使用skip
和take
方法来限制查询返回的结果数量,或在查询中跳过指定数量的结果
$users = DB::table('users')->skip(10)->take(5)->get();
或者,您可以使用limit
和offset
方法。这些方法在功能上分别等同于take和skip方法。
$users = DB::table('users') ->offset(10) ->limit(5) ->get();
插入语句
查询构建器还提供了一个insert
方法,可用于将记录插入到数据库表中。insert方法接受一个列名和值的数组。
DB::table('users')->insert([ 'email' => 'kayla@example.com', 'votes' => 0 ]);
自动递增ID
如果表有一个自动递增的ID,则使用insertGetId
方法插入一条记录并检索ID。
$id = DB::table('users')->insertGetId( ['email' => 'john@example.com', 'votes' => 0] );
更新语句
除了将记录插入到数据库中,查询构建器还可以使用update方法更新现有记录。update方法与insert方法类似,接受一个列和值对的数组,指示要更新的列。update方法返回受影响的行数。您可以使用where子句约束更新查询。
$affected = DB::table('users') ->where('id', 1) ->update(['votes' => 1]);
递增和递减
查询构建器还提供了方便的方法来增加或减少给定列的值。这两个方法至少接受一个参数:要修改的列。可以提供一个第二个参数来指定列应增加或减少的量。
DB::table('users')->increment('votes'); DB::table('users')->increment('votes', 5); DB::table('users')->decrement('votes'); DB::table('users')->decrement('votes', 5);
删除语句
DB::table('users')->where('id', $id)->delete();
特殊功能
您可以使用更令人愉悦的语法,这不仅可以缩短代码,还可以使代码更易读。
方法:is / true / false
要基于布尔值创建查询,您可以使用true
和false
或is
方法。
$active_list = DB::table('users')->is('active')->get(); // OR $active_list = DB::table('users')->true('active')->get();
$inactive_list = DB::table('users')->is('active', false)->get(); //OR $inactive_list = DB::table('users')->false('active')->get();
方法:and / or / in
您不需要连续使用where方法进行查询。您可以使用and方法或使用or代替orWhere。
示例
DB::table('users') ->is('active') ->and('credit', '>', 0) ->or('vip', true) ->get();
DB::table('users') ->in('id', [1,5,10]) ->get();
其他方法也是可用的,如下所示的方法
not(..)
/ orNot(..)
in(..)
/ notIn(..)
/ orIn(..)
/ orNotIn(..)
like(..)
/ orLike(..)
null(..)
/ orNull(..)
/ notNull(..)
/ orNotNull(..)
date(..)
/ orDate(..)
year(..)
/ orYear(..)
month(..)
/ orMonth(..)
day(..)
/ orDay(..)
time(..)
/ orTime(..)