webrium/foxql

Foxdb 查询构建器

3.0.1 2024-09-02 08:00 UTC

README

Latest Stable Version Total Downloads Latest Unstable Version License

属性

  • ✔️ 资源使用低
  • ✔️ 更轻量更快
  • ✔️ 与 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 方法,您可以指定查询的定制“选择”子句。

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();

在这个结构中,您可以使用 fieldcountsumavgminmaxallas 方法。


原始方法

除了使用 DB::raw 方法外,您还可以使用以下方法将原始表达式插入查询的各个部分。请记住,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();

内连接子句

查询构建器还可以用于向查询中添加连接子句。要执行基本的“内连接”,您可以使用查询构建器实例上的 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')。


左连接 / 右连接子句

如果您想执行“左连接”或“右连接”而不是“内连接”,请使用 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 方法执行“交叉连接”。交叉连接生成第一个表和连接表的笛卡尔积。

$sizes = DB::table('sizes')
            ->crossJoin('colors')
            ->get();

WHERE 子句

您可以使用查询构建器的 where 方法向查询中添加“where”子句。where 方法的最基本调用需要三个参数。第一个参数是列名。第二个参数是一个运算符,可以是数据库支持的所有运算符中的任何一个。第三个参数是与列值比较的值。

例如,以下查询检索了 votes 列值为 100 且 age 列值大于 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 操作符连接在一起。但是,您可以使用 orWhere 方法使用 or 操作符将一个子句连接到查询中。orWhere 方法接受与 where 方法相同的参数。

$users = DB::table('users')
                    ->where('votes', '>', 100)
                    ->orWhere('name', 'John')
                    ->get();

如果您需要在括号内分组 "or" 条件,可以将闭包作为 orWhere 方法的第一个参数传递。

$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 子句

whereNotorWhereNot 方法可以用来否定一组查询约束。例如,以下查询排除了正在清仓或价格低于十的产品。

$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();

最新 & 最老 方法

latestoldest 方法允许您轻松按日期排序结果。默认情况下,结果将按表的 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方法

您可以使用skiptake方法来限制查询返回的结果数量,或者跳过查询中给定数量的结果

$users = DB::table('users')->skip(10)->take(5)->get();

或者,您可以使用limitoffset方法。这些方法的功能与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

要创建基于布尔值的查询,可以使用truefalseis方法

$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(..)