数据库操作

几乎所有的应用程序都需要和数据库进行交互。Laravel 为此提供了一套非常简单易用的数据库交互方式。开发者可以使用原生 SQL、查询构造器 以及 Eloquent ORM 等方式与数据库交互

配置文件

数据库的配置文件在 config/database.php 文件中。你可以在这个文件中配置所有的数据库连接,并指定默认的数据库连接,该文件中的大部分配置都基于项目的环境变量,且提供了大部分 Laravel 所支持的数据库配置示例

执行原生 SQL 查询

一旦配置好数据库连接,你就可以使用 DB Facade 来执行查询。DB Facade 为每种类型的查询都提供了相应的方法:selectupdateinsertdelete 以及 statement

执行 SELECT 查询

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;

class UserController extends Controller
{
    /**
     * 展示用户列表
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $users = DB::select('SELECT * FROM `users` WHERE `active` = ?', [1]);

        return view('user.index', ['users' => $users]);
    }
}

传递给 select 方法的第一个参数是一个原生 SQL 查询语句,而第二个参数则是需要绑定到查询中的参数值。通常,这些值用于约束 where 语句。使用参数绑定可以有效防止 SQL 注入。

select 方法将始终返回一个包含查询结果的数组。数组中的每个结果都会是一个代表数据库记录的 stdClass 对象

use Illuminate\Support\Facades\DB;

$users = DB::select('select * from users');

foreach ($users as $user) {
    echo $user->name;
}

使用命名绑定

除了使用 ? 表示参数绑定外,也可以使用命名绑定的形式来执行一个查询

$results = DB::select('select * from users where id = :id', ['id' => 1]);

执行 INSERT 查询

你可以使用 DB Facadeinsert 方法来执行 insert 语句。跟 select 方法一样,该方法的第一个和第二个参数分别是原生 SQL 语句和绑定的数据

use Illuminate\Support\Facades\DB;

DB::insert('insert into users (id, name) values (?, ?)', [1, 'Marc']);

执行 UPDATE 查询

update 方法用于更新数据库中现有的记录。该方法将会返回受到本次操作影响的记录行数

use Illuminate\Support\Facades\DB;

$affected = DB::update(
    'update users set votes = 100 where name = ?',
    ['Anita']
);

执行 DELETE 语句

delete 方法用于从数据库中删除现有的记录。与 update 方法一样,返回受到本次操作影响的记录行数

use Illuminate\Support\Facades\DB;

$deleted = DB::delete('delete from users');

执行普通查询

部分数据库语句没有返回值。对于这些语句,你可以使用 DB Facadestatement 方法

DB::statement('drop table users');

数据库事务

你可以使用 DB Facadetransaction 方法在数据库事务中运行一系列操作。如果事务的闭包中出现了异常,Laravel 将会自动回滚该事务。如果该闭包执行成功,事务将会被自动提交。你完全不需要担心手动回滚或者提交的问题

use Illuminate\Support\Facades\DB;

DB::transaction(function () {
    DB::update('update users set votes = 1');

    DB::delete('delete from posts');
});

处理死锁

transaction 方法接受一个可选的第二参数,该参数用于表示事务在遇到死锁时尝试重新执行的次数。如果尝试指定次数后依然无法执行,将会抛出一个异常

use Illuminate\Support\Facades\DB;

DB::transaction(function () {
    DB::update('update users set votes = 1');

    DB::delete('delete from posts');
}, 5);

手动执行事务

如果您想手动开始事务并完全控制回滚和提交,则可以使用 beginTransaction 提供的方法 DB

use Illuminate\Support\Facades\DB;

DB::beginTransaction();

您可以通过以下 rollBack 方法回滚事务

DB::rollBack();

最后,您可以通过以下 commit 方法提交事务

DB::commit();

查询构造器

Laravel 的数据库查询构造器为创建和运行数据库查询提供了一个方便的接口。它可以用于支持大部分数据库操作,并与 Laravel 支持的所有数据库系统完美运行

查询所有数据

你可以使用 DB facade 里的 table 方法来开始查询。table 方法为给定的表返回一个查询构造器实例,允许你在查询上链式调用更多的约束,最后使用 get 方法获取结果

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;

class UserController extends Controller
{
    /**
     * 展示所有用户数据。
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $users = DB::table('users')->get();

        return view('user.index', ['users' => $users]);
    }
}

get 方法返回一个包含 Illuminate\Support\Collection 的结果,其中每个结果都是 PHP StdClass 对象的一个实例。你可以访问字段作为对象的属性来访问每列的值

use Illuminate\Support\Facades\DB;

$users = DB::table('users')->get();

foreach ($users as $user) {
    echo $user->name;
}

从数据表中获取单行或单列

如果你只需要从数据表中获取一行数据,你可以使用 first 方法。该方法返回一个 StdClass 对象

$user = DB::table('users')->where('name', 'John')->first();

return $user->email;

如果你不需要整行数据,则可以使用 value 方法从记录中获取单个值。该方法将直接返回该字段的值

$email = DB::table('users')->where('name', 'John')->value('email');

如果是通过 id 字段值获取一行数据,可以使用 find 方法

$user = DB::table('users')->find(3);

获取一列的值

use Illuminate\Support\Facades\DB;

$titles = DB::table('users')->pluck('title');

foreach ($titles as $title) {
    echo $title;
}

聚合

查询构造器还提供了各种聚合方法,比如 countmaxminavg,还有 sum。你可以在构造查询后调用任何方法

use Illuminate\Support\Facades\DB;

// 查询数据总数
$users = DB::table('users')->count();

// 查询某个字段的最大值
$price = DB::table('orders')->max('price');

Select

如果不想从数据库表中获取所有列。那么可以使用 select 方法来查询指定的字段

use Illuminate\Support\Facades\DB;

$users = DB::table('users')
            ->select('name', '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();

Join 链表查询

Inner Join 内链表
use Illuminate\Support\Facades\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();
Left Join 左链表
use Illuminate\Support\Facades\DB;

$users = DB::table('users')
            ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
            ->get();
Right Join 右链表
use Illuminate\Support\Facades\DB;

$users = DB::table('users')
            ->rightJoin('posts', 'users.id', '=', 'posts.user_id')
            ->get();

Union 联合查询

查询构造器还提供了一种简洁的方式将两个或者多个查询联合在一起。例如,你可以先创建一个查询,然后使用 union 方法来连接更多的查询

use Illuminate\Support\Facades\DB;

$first = DB::table('users')
            ->whereNull('first_name');

$users = DB::table('users')
            ->whereNull('last_name')
            ->union($first)
            ->get();

where 条件查询

<?php
namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;

class UserController extends Controller
{
    /**
     * 展示用户列表
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        /* 
            第一个参数 => 字段名
            第二个参数 => 操作符 如果把指定的值作为第二个参数时,laravel会默认使用 = 操作符
            第三个参数 => 指定的值或者比较字段的值
        */
        $users = DB::table('users')
                ->where('votes', '=', 100)
                ->where('age', '>', 35)
                ->get();

        // votes 大于等于 100
        $users = DB::table('users')
                ->where('votes', '>=', 100)
                ->get();

        // votes 不等于 1000
        $users = DB::table('users')
                ->where('votes', '<>', 100)
                ->get();

        // 模糊查询name以T开头
        $users = DB::table('users')
                ->where('name', 'like', 'T%')
                ->get();

        // 条件数组
        $users = DB::table('users')->where([
            ['status', '=', '1'],
            ['subscribed', '<>', '1'],
        ])->get();
    }
}

orWhere

当链式调用多个 where 方法的时候,这些 where 语句将会被看成是 and 关系。另外,您也可以在查询语句中使用 orWhere 方法来表示 or 关系。orWhere 方法接收的参数和 where 方法接收的参数一样

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;

class UserController extends Controller
{
    public function index()
    {
        $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();
    }
}

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

Ordering, Grouping, Limit

orderBy 方法允许你通过给定字段对结果集进行排序。 orderBy 的第一个参数应该是你希望排序的字段,第二个参数控制排序的方向,可以是 ascdesc

$users = DB::table('users')
            ->orderBy('name', 'desc')
            ->get();

如果你需要使用多个字段进行排序,你可以多次引用 orderBy

$users = DB::table('users')
            ->orderBy('name', 'desc')
            ->orderBy('email', 'asc')
            ->get();

groupByhaving 方法用于将结果分组。 having 方法的使用与 where 方法十分相似

$users = DB::table('users')
            ->groupBy('account_id')
            ->get();

可以向 groupBy 方法传递多个参数,来对结果使用多个字段进行分组

$users = DB::table('users')
            ->groupBy('first_name', 'status')
            ->having('account_id', '>', 100)
            ->get();

limit 方法用于限制结果的返回数量

$users = DB::table('users')
            ->limit(5)
            ->get();

插入语句

查询构造器还提供了 insert 方法用于插入记录到数据库中。 insert 方法接收数组形式的字段名和字段值进行插入操作

DB::table('users')->insert([
    'email' => 'kayla@example.com',
    'votes' => 0
]);

你甚至可以将二维数组传递给 insert 方法,依次将多个记录插入到表中

自增 IDs

如果数据表有自增 ID ,使用 insertGetId 方法来插入记录可以返回 ID 值

$id = DB::table('users')->insertGetId(
    ['email' => 'john@example.com', 'votes' => 0]
);

更新语句

除了插入记录到数据库中,查询构造器也可以通过 update 方法更新已有的记录。 update 方法和 insert 方法一样,接受包含要更新的字段及值的数组

$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')->increment('votes', 1, ['name' => 'John']);

删除语句

查询构造器也可以使用 delete 方法从表中删除记录。 在使用 delete 前,可以添加 where 子句来约束 delete 语法

DB::table('users')->delete();

DB::table('users')->where('votes', '>', 100)->delete();

调试

在绑定查询的时候,您可以使用 dddump 方法来输出查询绑定和 SQL。dd 方法将会显示调试信息并终止执行请求,而 dump 方法则会显示调试信息并允许请求继续执行

DB::table('users')->where('votes', '>', 100)->dd();

DB::table('users')->where('votes', '>', 100)->dump();
powered by GitbookEdit Time: 2023-04-08 10:28:32