目录

Laravel 常用函数

目录

概述

发行说明 - Laravel

对于所有 Laravel 发行版本,BUG 修复的期限为 18 个月,安全修复的期限为 2 年。对于包括 Lumen 在内的所有额外的库,只有最新的版本才会得到 BUG 修复。

本文基于 Laravel 8.x 版本

版本PHP (*)发行时间Bug 修复截止时间安全修复截止时间
6 (LTS)7.2 - 8.02019 年 9 月 3 日2022 年 1 月 25 日2022 年 9 月 6 日
77.2 - 8.02020 年 3 月 3 日2020 年 10 月 6 日2021 年 3 月 3 日
87.3 - 8.12020 年 9 月 8 日2022 年 7 月 26 日2023 年 1 月 24 日
98.0 - 8.12022 年 2 月 8 日2023 年 8 月 8 日2024 年 2 月 8 日
108.12023 年 2 月 7 日2024 年 8 月 7 日2025 年 2 月 7 日

请求路由

路由 |《Laravel 8.x》

常规路由

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Route::get('foo', function () {
    return 'Hello World';
});

Route::get('/user', 'UserController@index');

Route::match(['get', 'post'], '/', function () {
    //
});

Route::get('config/list','Common\Config@list');
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// 路由命名,控制器中跳转至指定的路由
Route::get('user/profile', 'UserProfileController@show')->name('profile');
// 生成 URL...
$url = route('profile');
// 控制器中生成重定向...
return redirect()->route('profile');

// 传参方式
Route::get('user/{id}/profile', function ($id) {
    //
})->name('profile');

$url = route('profile', ['id' => 1]);

路由分组

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // 匹配包含 「/admin/users」 的 URL
    });
});

Route::name('admin.')->group(function () {
    Route::get('users', function () {
        // 指定路由名为 「admin.users」... (不影响请求get路由)
    })->name('users');
});
1
2
3
4
// {注意} 回退路由应始终是你应用程序注册的最后一个路由。
Route::fallback(function () {
    // 类似 404 页面,匹配不到任何路由的时候走到该方法
});

路由中间键

路由 |《Laravel 8.x》

1
2
3
4
5
6
// 限流方式
Route::middleware('auth:api', 'throttle:60,1')->group(function () {
    Route::get('/user', function () {
        //
    });
}); 

控制器中获取请求内容

接收请求

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 无值情况 $name === null
// 检索 body 和 url 中参数,两则都有的情况下 body 内容优先。
$name = $request->input('name');

// 获取请求数据数组
$input = $request->all();

// 只取指定的参数,不存在的值 === null,key 依然存在
/*
?name=2&age=10
array:2 [
  "name" => "2"
  "a1" => null
]
*/
$input = $request->all(['name','a1']);

// 只取指定的参数,不存在的值不会有 key,有值并且是空字符串时候,值 === null
/* 
?name=2&age=10&a1=
array:2 [
  "name" => "2"
  "a1" => null
]

?name=2&age=10
array:1 [
  "name" => "2"
]
*/
$input = $request->only(['name','a1']);

获取上传的文件

请求 |《Laravel 8.x》

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$file = $request->file('photo');

$file = $request->photo;

// 判断是否为文件
if ($request->hasFile('photo')) {
    //
}

// 获取上传临时文件路径
// "/tmp/phpxXRXuy"
$path = $request->photo->path();
// 获取扩展名
// "png"
$extension = $request->photo->extension();
// 获取文件原始文件名
// "Snipaste_2021-09-24_10-09-55.png"
$name = $request->photo->->getClientOriginalName();

表单校验

表单验证 |《Laravel 8.x》

快速校验

1
2
3
4
$validatedData = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

手动创建验证器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$validator = Validator::make(request()->all(), [
    'title' => 'required|unique:posts|max:255',
    'body'  => 'required',
]);

if ($validator->fails()) {
    //array:2 [
    //  0 => "title"
    //  1 => "body"
    //]
    $keys = $validator->errors()->keys(); // 错误的全部 key
    // "标题 不能为空。" 第一个错误信息
    dd($validator->errors()->first());
}

表单验证 |《Laravel 8.x》

1
2
3
4
5
6
7
// 自定义错误信息
// :attribute 占位符会被验证字段的实际名称替换
$messages = [
    'required' => 'The :attribute field is required.',
];

$validator = Validator::make($input, $rules, $messages);

控制器可用校验规则

表单验证 |《Laravel 8.x》

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
[
    // 验证的字段必须存在于输入数据中,而不是空。
    // 空字符串、空数组、无效上传文件、值为 null 都不能过校验。
    'key' => 'required',

    // 验证字段必须包含在给定的值列表中。
    'type' => 'required|in:1,2,3,4,5',

    // 校验参数范围 1< page_size < 1000 (整数)
    'page_size'   => 'required|integer|between:1,1000',
    // 校验参数范围 1< float < 1000 (可为小数)
    'float'   => 'required|numeric|between:1,1000',

    // 校验字符个数 必须介于 1 - 2 个字符之间。
    'body'  => 'required|between:1,2',

    // 正则表达式匹配,修饰符
    // 不通过提示 "mp4 格式不正确。"
    'mp4' => 'regex:/^\w+\.mp4$/i',
]

collect 集合

集合 |《Laravel 8.x》

创建集合

1
$collection = collect([1, 2, 3]);

扩展集合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Collection::macro('toUpper', function () {
    return $this->map(function ($value) {
        return Str::upper($value);
    });
});

$collection = collect(['first', 'second']);

$upper = $collection->toUpper();

// ['FIRST', 'SECOND']

all 获取底层数组

1
2
3
4
// 注意:只有第一层会变成数组,其他嵌套对象保持原样。
collect([1, 2, 3])->all();

// [1, 2, 3]

toArray 集合转数组

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 注意:toArray 也会将所有集合的嵌套对象转换为数组。如果你想获取原数组,可以使用 all 方法。
$collection = collect(['name' => 'Desk', 'price' => 200]);

$collection->toArray();

/*
[
    "name" => "Desk"
    "price" => 200
]
*/

get 取键的集合项

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$value = $collection->get('name');
// taylor

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$value = $collection->get('foo', 'default-value');
// default-value

$collection->get('email', function () {
    return 'default-value';
});
// default-value

chunk 将集合拆开成块

1
2
3
4
5
6
7
$collection = collect([1, 2, 3, 4, 5, 6, 7]);

$chunks = $collection->chunk(4);

$chunks->toArray();

// [[1, 2, 3, 4], [5, 6, 7]]

collapse 二维转一维

1
2
3
4
5
6
7
$collection = collect([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);

$collapsed = $collection->collapse();

$collapsed->all();

// [1, 2, 3, 4, 5, 6, 7, 8, 9]

each 循环集合项只做循环

1
2
3
4
5
6
// 只做循环操作,不会改变原始集合内容
$collection->each(function ($item, $key) {
    if (/* some condition */) {
        return false; // 中断循环
    }
});

map 遍历生成新集合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$collection = collect([1, 2, 3, 4, 5]);

// 创建一个新集合
$multiplied = $collection->map(function ($item, $key) {
    return $item * 2;
});

$multiplied->all();

// [2, 4, 6, 8, 10]

transform 遍历改变原集合

1
2
3
4
5
6
7
8
9
$collection = collect([1, 2, 3, 4, 5]);

$collection->transform(function ($item, $key) {
    return $item * 2;
});

$collection->all();

// [2, 4, 6, 8, 10]

filter 保留满足条件项

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$collection = collect([1, 2, 3, 4]);

$filtered = $collection->filter(function ($value, $key) {
    return $value > 2;
});

$filtered->all();

// [3, 4]

// 未提供回调函数 过滤空值
$collection = collect([1, 2, 3, null, false, '', 0, []]);

$collection->filter()->all();

// [1, 2, 3]

reject 丢弃满足条件项

1
2
3
4
5
6
7
8
9
$collection = collect([1, 2, 3, 4]);

$filtered = $collection->reject(function ($value, $key) {
    return $value > 2;
});

$filtered->all();

// [1, 2]

first 取满足条件的第一个

1
2
3
4
5
6
7
8
9
collect([1, 2, 3, 4])->first(function ($value, $key) {
    return $value > 2;
});

// 3

collect([1, 2, 3, 4])->first();

// 1

implode 集合转字符串

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$collection = collect([
    ['account_id' => 1, 'product' => 'Desk'],
    ['account_id' => 2, 'product' => 'Chair'],
]);

$collection->implode('product', ', ');

// Desk, Chair

collect([1, 2, 3, 4, 5])->implode('-');

// '1-2-3-4-5'

join 集合转字符串

1
2
3
4
5
collect(['a', 'b', 'c'])->join(', '); // 'a, b, c'
collect(['a', 'b', 'c'])->join(', ', ', and '); // 'a, b, and c'
collect(['a', 'b'])->join(', ', ' and '); // 'a and b'
collect(['a'])->join(', ', ' and '); // 'a'
collect([])->join(', ', ' and '); // ''

isEmpty 判断空集合

1
2
3
collect([])->isEmpty();

// true

keyBy 指定键值为键

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$collection = collect([
    ['product_id' => 'prod-100', 'name' => 'Desk'],
    ['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$keyed = $collection->keyBy('product_id');

$keyed->all();

/*
    [
        'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
        'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
    ]
*/

// 使用回调函数
$keyed = $collection->keyBy(function ($item) {
    return strtoupper($item['product_id']);
});

$keyed->all();

/*
    [
        'PROD-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
        'PROD-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
    ]
*/

keys 返回集合键

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$collection = collect([
    'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
    'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$keys = $collection->keys();

$keys->all();

// ['prod-100', 'prod-200']

merge 合并集合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 带 key 值的项合并,同名 key 后面的覆盖前面的项。
$collection = collect(['product_id' => 1, 'price' => 100]);
$merged = $collection->merge(['price' => 200, 'discount' => false]);
$merged->all();
// ['product_id' => 1, 'price' => 200, 'discount' => false]

$collection = collect(['Desk', 'Chair']);
$merged = $collection->merge(['Bookcase', 'Door']);
$merged->all();
// ['Desk', 'Chair', 'Bookcase', 'Door']

union 合并集合

1
2
3
4
5
6
7
8
9
// 带 key 值的项合并,同名 key 后面的忽略。
$collection = collect([1 => ['a'], 2 => ['b']]);
$union = $collection->union([3 => ['c'], 1 => ['b']]);
$union->all();
// [1 => ['a'], 2 => ['b'], 3 => ['c']]

// 根据数组的 key 进行合并
collect([1, 2, 3])->union([4, 5, 6, 7, 8])->all();
//[1, 2, 3, 7, 8]

only 获取指定键的项

1
2
3
4
5
6
7
8
// 不存在的 Key 不会在结果中展示
$collection = collect(['product_id' => 1, 'name' => 'Desk', 'price' => 100, 'discount' => false]);

$filtered = $collection->only(['product_id', 'name', 'date']);

$filtered->all();

// ['product_id' => 1, 'name' => 'Desk']

pluck 获取指定键值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 将指定键的值组成一个数组
$collection = collect([
    ['product_id' => 'prod-100', 'name' => 'Desk'],
    ['product_id' => 'prod-200', 'name' => 'Chair'],
]);
$plucked = $collection->pluck('name');
$plucked->all();
// ['Desk', 'Chair']
// 可另外指定第二个参数,当成新集合的键。(如果有重复项,则取数组最后的项)
$plucked = $collection->pluck('name', 'product_id');
$plucked->all();
// ['prod-100' => 'Desk', 'prod-200' => 'Chair']

values 重置键

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$collection = collect([
    10 => ['product' => 'Desk', 'price' => 200],
    11 => ['product' => 'Desk', 'price' => 200]
]);

$values = $collection->values();

$values->all();

/*
    [
        0 => ['product' => 'Desk', 'price' => 200],
        1 => ['product' => 'Desk', 'price' => 200],
    ]
*/

push 追加元素

1
2
3
4
$collection = collect([1, 2, 3, 4]);
$collection->push(5);
$collection->all();
// [1, 2, 3, 4, 5]

put 指定键值对追加

1
2
3
4
$collection = collect(['product_id' => 1, 'name' => 'Desk']);
$collection->put('price', 100);
$collection->all();
// ['product_id' => 1, 'name' => 'Desk', 'price' => 100]

sortBy 根据二维数组内排序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$collection = collect([
    ['name' => 'Desk', 'price' => 200],
    ['name' => 'Chair', 'price' => 100],
    ['name' => 'Bookcase', 'price' => 150],
]);
$sorted = $collection->sortBy('price');
$sorted->values()->all();
/*
    [
        ['name' => 'Chair', 'price' => 100],
        ['name' => 'Bookcase', 'price' => 150],
        ['name' => 'Desk', 'price' => 200],
    ]
*/

// 自定义排序方式
$collection = collect([
    ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
    ['name' => 'Chair', 'colors' => ['Black']],
    ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);
$sorted = $collection->sortBy(function ($product, $key) {
    return count($product['colors']);
});
$sorted->values()->all();
/*
    [
        ['name' => 'Chair', 'colors' => ['Black']],
        ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
        ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
    ]
*/

数据库

原生 SQL

快速入门 |《Laravel 8.x》

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$users = DB::connection('foo')->select(...);
$pdo = DB::connection()->getPdo();

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

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

// 返回受该语句影响的行数
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
// 返回受该语句影响的行数
$deleted = DB::delete('delete from users');

// 执行不需要任何返回值的 sql
DB::statement('drop table users');

数据库事务

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 自动事务
DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);
    DB::table('posts')->delete();
});

// 手动处理事务
DB::beginTransaction(); // 开始
DB::rollBack(); // 回滚
DB::commit(); // 提交

// Tip:DB facade 的事务方法同样适用于 查询构造器 和 Eloquent ORM 。

查询构造器

普通结果查询

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 查询获取所有行
$users = DB::table('users')->get();

// 查询单行
$user = DB::table('users')->where('name', 'John')->first();

// 查询单值
$email = DB::table('users')->where('name', 'John')->value('email');

// 查询单列值的集合
$titles = DB::table('roles')->pluck('title');
$roles = DB::table('roles')->pluck('title', 'name'); // 值 - 键
foreach ($roles as $name => $title) {
    echo $title;
}

// 分块结果
DB::table('users')->orderBy('id')->chunk(100, function ($users) {
    foreach ($users as $user) {

        // return false; // 中断继续获取分块结果
    }
});

// 更新型分块 - 根据 ID 来处理结果。(查询条件有被更新操作)
DB::table('users')->where('active', false)
    ->chunkById(100, function ($users) {
        foreach ($users as $user) {
            DB::table('users')
                ->where('id', $user->id)
                ->update(['active' => true]);
        }
    });

聚合查询

1
2
3
4
$users = DB::table('users')->count();
$price = DB::table('orders')->max('price');
$price = DB::table('orders')->where('finalized', 1)->avg('price');
DB::table('orders')->where('finalized', 1)->exists();

select 指定列、去重

1
2
3
4
5
6
$users = DB::table('users')->select('name', 'email as user_email')->get();
$users = DB::table('users')->distinct()->get(); // 排重

// 新增字段
$query = DB::table('users')->select('name');
$users = $query->addSelect('age')->get();

原生表达式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$users = DB::table('users')
                     ->select(DB::raw('count(*) as user_count, status'))
                     ->where('status', '<>', 1)
                     ->groupBy('status')
                     ->get();

$orders = DB::table('orders')
                ->selectRaw('price * ? as price_with_tax', [1.0825])
                ->get();

$orders = DB::table('orders')
                ->whereRaw('price > IF(state = "TX", ?, 100)', [200])
                ->get();

$orders = DB::table('orders')
                ->select('department', DB::raw('SUM(price) as total_sales'))
                ->groupBy('department')
                ->havingRaw('SUM(price) > ?', [2500])
                ->get();

$orders = DB::table('orders')
                ->orderByRaw('updated_at - created_at DESC')
                ->get();

Join

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// inner join
$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 / Right 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();

// 高级 join 用法
DB::table('users')
        ->join('contacts', function ($join) {
            $join->on('users.id', '=', 'contacts.user_id')->orOn(...);
        })
        ->get();

DB::table('users')
        ->join('contacts', function ($join) {
            $join->on('users.id', '=', 'contacts.user_id')
                 ->where('contacts.user_id', '>', 5);
        })
        ->get();

// 子连接查询

$latestPosts = DB::table('posts')
                   ->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))
                   ->where('is_published', true)
                   ->groupBy('user_id');

$users = DB::table('users')
    // 接收三个参数:子查询、表别名、定义关联字段的闭包
        ->joinSub($latestPosts, 'latest_posts', function ($join) {
            $join->on('users.id', '=', 'latest_posts.user_id');
        })->get();

union

1
2
3
4
5
6
7
$first = DB::table('users')
            ->whereNull('first_name');

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

where

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$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('votes', '<>', 100)->get();
$users = DB::table('users')->where('name', 'like', 'T%')->get();
$users = DB::table('users')->where([
    ['status', '=', '1'],
    ['subscribed', '<>', '1'],
])->get();
$users = DB::table('users')->whereBetween('votes', [1, 100])->get();
$users = DB::table('users')->whereIn('id', [1, 2, 3])->get();
// 比较两个字段相等
$users = DB::table('users')->whereColumn('first_name', 'last_name')->get();
$users = DB::table('users')->whereColumn([
                    ['first_name', '=', 'last_name'],
                    ['updated_at', '>', 'created_at'],
                ])->get();
// 子查询
$users = DB::table('users')->whereExists(function ($query) {
               $query->select(DB::raw(1))
                     ->from('orders')
                     ->whereRaw('orders.user_id = users.id');
           })->get();
/*
select * from users
where exists (
    select 1 from orders where orders.user_id = users.id
) 
*/

where json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 仅支持 MySQL 5.7+ JSON 类型支持的数据库
$users = DB::table('users')
                ->where('options->language', 'en')
                ->get();

$users = DB::table('users')
                ->where('preferences->dining->meal', 'salad')
                ->get();

$users = DB::table('users')
                ->whereJsonContains('options->languages', 'en')
                ->get();

$users = DB::table('users')
                ->whereJsonContains('options->languages', ['en', 'de'])
                ->get();

$users = DB::table('users')
                ->whereJsonLength('options->languages', 0)
                ->get();

$users = DB::table('users')
                ->whereJsonLength('options->languages', '>', 1)
                ->get();

order group limit offset

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$users = DB::table('users')
                ->orderBy('name', 'desc') // 降序
                ->get();

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

// 通常使用 chunk 就行
$users = DB::table('users')->skip(10)->take(5)->get();
$users = DB::table('users')->offset(10)->limit(5)->get();

when 条件语句

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 第一个参数为 true 才会丢给闭包 
$role = $request->input('role');
$users = DB::table('users')->when($role, function ($query, $role) {
                    return $query->where('role_id', $role);
                })->get();
// 第三个参数是第一个参数为 false 时执行的
$sortBy = null;
$users = DB::table('users')->when($sortBy, function ($query, $sortBy) {
                    return $query->orderBy($sortBy);
                }, function ($query) {
                    return $query->orderBy('name');
                })->get();

insert

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
DB::table('users')->insert(
    ['email' => 'john@example.com', 'votes' => 0]
);

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

// insertOrIgnore 方法用于忽略重复插入记录到数据库的错误:
DB::table('users')->insertOrIgnore([
    ['id' => 1, 'email' => 'taylor@example.com'],
    ['id' => 2, 'email' => 'dayle@example.com']
]);

// 插入并获取自增 ID
$id = DB::table('users')->insertGetId(
    ['email' => 'john@example.com', 'votes' => 0]
);

update

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$affected = DB::table('users')
              ->where('id', 1)
              ->update(['votes' => 1]);

// 第一个参数用于查询,存在则更新不存在则插入。
DB::table('users')
    ->updateOrInsert(
        ['email' => 'john@example.com', 'name' => 'John'],
        ['votes' => '2']
    );

// 更新 json
$affected = DB::table('users')
              ->where('id', 1)
              ->update(['options->enabled' => true]);

// 自增自减
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

1
2
3
DB::table('users')->delete();
DB::table('users')->where('votes', '>', 100)->delete();
DB::table('users')->truncate(); // 清空表并重置自增 ID

分页

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$users = DB::table('users')->paginate(15); // size ,会自动检测 page
$users = DB::table('users')->simplePaginate(15); // 简单分页,只有上一页下一页

$results->count();                      // 获取当前页数据的数量。
$results->currentPage();                // 获取当前页页码。
$results->firstItem();                  // 获取结果集中第一条数据的结果编号。
$results->getOptions();                 // 获取分页器选项。
$results->getUrlRange($start, $end);    // 创建分页 URL 的范围。
$results->hasMorePages();               // 是否有多页。
$results->items();                      // 获取当前页的所有项。
$results->lastItem();                   // 获取结果集中最后一条数据的结果编号。
$results->lastPage();                   // 获取最后一页的页码。(在 simplePaginate 无效)。
$results->nextPageUrl();                // 获取下一页的 URL。
$results->onFirstPage();                // 当前页是否为第一页。
$results->perPage();                    // 每页的数据条数。
$results->previousPageUrl();            // 获取前一页的 URL。
$results->total();                      // 数据总数(在 simplePaginate 无效)。
$results->url($page);                   // 获取指定页的 URL。

ORM

快速入门 |《Laravel 8.x》

创建 model

1
2
3
4
5
php artisan make:model Flight

// 同时生成数据库迁移
php artisan make:model Flight --migration
php artisan make:model Flight -m

Eloquent 模型约定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
protected $table = 'my_flights'; // 表名
protected $primaryKey = 'flight_id'; // 重定义主键,默认主键为 id
public $timestamps = false; // 不需要自动维护 created_at updated_at
protected $dateFormat = 'U'; // 模型日期格式设置为时间戳,默认为 string 类型时间
const CREATED_AT = 'creation_date'; // 重新设置创建日期字段名
const UPDATED_AT = 'last_update'; // 重新设置修改日期字段名
protected $connection = 'connection-name'; // 选择指定连
protected $attributes = [ // 设置默认属性
    'delayed' => false,
];
protected $fillable = ['name']; // 可以被批量赋值的属性。
protected $guarded = ['price']; // 不可批量赋值的属性。
protected $guarded = []; // 所有属性都可以批量赋值
protected $hidden = ['password']; // 隐藏某些字段

protected $casts = [ // 属性类型转换
    'birthday' => 'date:Y-m-d',
    'joined_at' => 'datetime:Y-m-d H:00',
    'is_admin' => 'boolean',
    'options' => 'array', // 数据库中 JSON 使用时自动转换成数组,存入时候,数组也会自动转成 json
];

分块结果

1
2
3
4
5
Flight::chunk(200, function ($flights) {
    foreach ($flights as $flight) {
        //
    }
});

游标

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 允许你使用游标遍历数据库,它只执行一次查询。
foreach (Flight::where('foo', 'bar')->cursor() as $flight) {
    //
}

$users = App\User::cursor()->filter(function ($user) {
    return $user->id > 500;
});
foreach ($users as $user) {
    echo $user->id;
}

查询单条数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 通过主键检索一个模型...
$flight = App\Flight::find(1);
$flights = App\Flight::find([1, 2, 3]);

// 检索符合查询限制的第一个模型...
$flight = App\Flight::where('active', 1)->first();

// 未找到产生一个异常
$model = App\Flight::findOrFail(1);
$model = App\Flight::where('legs', '>', 100)->firstOrFail();

插入更新数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// 插入数据,会自动维护创建时间和更新时间
$flight = new Flight;
$flight->name = $request->name;
$flight->save(); // 插入

// 更新操作,自动维护更新时间
$flight = App\Flight::find(1);
$flight->name = 'New Flight Name';
$flight->save();

// 批量更新,(通过 Eloquent 批量更新时, 更新的模型不会触发 saved 和 updated 事件。)
App\Flight::where('active', 1)
          ->where('destination', 'San Diego')
          ->update(['delayed' => 1]);

// 批量赋值,注意:需定义 $fillable 或 $guarded
$flight = App\Flight::create(['name' => 'Flight 10']);
$flight->fill(['name' => 'Flight 22']); // 通过已有模型

// 其他创建方法

firstOrCreate firstOrNew

试图找到记录(或创建该记录,如果找不到)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 通过 name 来查找航班,不存在则创建... (直接插入数据)
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);

// 通过 name 查找航班,不存在则使用 name、 delayed 和 arrival_time 属性创建...
$flight = App\Flight::firstOrCreate(
    ['name' => 'Flight 10'], // 查询条件
    ['delayed' => 1, 'arrival_time' => '11:30'] // 修改内容
);
// 总结:如果第一个参数找到记录后,直接返回数据(不会根据第二个参数进行修改)。

//  通过 name 查找航班,不存在则创建一个实例... (只是生成一个实例)
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);

// 通过 name 查找航班,不存在则使用 name 和 delayed 属性创建一个实例...
$flight = App\Flight::firstOrNew(
    ['name' => 'Flight 10'],
    ['delayed' => 1, 'arrival_time' => '11:30']
);

updateOrCreate

期望使用所提供的数据更新现有记录(如果尚未存在,则创建该记录)。

1
2
3
4
5
6
7
// 如果没匹配到存在的模型,则创建一个。
$flight = App\Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99, 'discounted' => 1]
);

// 通过现有的全部数据覆盖库中的数据,(如果通过第一个参数找到值则做更新操作,未找到则做创建操作)

delete

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 通过模型删除
$flight = App\Flight::find(1);
$flight->delete();

// 通过主键删除
App\Flight::destroy(1);
App\Flight::destroy(1, 2, 3);
App\Flight::destroy([1, 2, 3]);
App\Flight::destroy(collect([1, 2, 3]));

// 通过查询删除,(批量删除不会为删除的模型启动任何模型事件)
$deletedRows = App\Flight::where('active', 0)->delete();

查询作用域

快速入门 |《Laravel 8.x》

全局作用域

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php
// 编写一个类
namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class AgeScope implements Scope
{
    /**
     * 把约束加到 Eloquent 查询构造中。
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        $builder->where('age', '>', 200);
    }
}

<?php
// 然后在 model 里面应用
namespace App;

use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 模型的「启动」方法
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope(new AgeScope);
    }
}

// 添加作用域后,对 User::all() 的查询会生成以下 SQL 查询语句:
// select * from `users` where `age` > 200

匿名作用域

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class User extends Model
{
    /**
     * 模型的「启动」方法
     *
     * @return void
     */
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope('age', function (Builder $builder) {
            $builder->where('age', '>', 200);
        });
    }
}

取消全局作用域

1
2
3
4
5
6
7
8
9
User::withoutGlobalScope(AgeScope::class)->get();
User::withoutGlobalScope('age')->get();
// 取消所有的全局作用域...
User::withoutGlobalScopes()->get();

// 取消部分全局作用域...
User::withoutGlobalScopes([
    FirstScope::class, SecondScope::class
])->get();

本地作用域

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
// 模型方法添加 scope 前缀。
namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 只查询受欢迎的用户的作用域
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePopular($query)
    {
        return $query->where('votes', '>', 100);
    }

    /**
     * 只查询 active 用户的作用域
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeActive($query)
    {
        return $query->where('active', 1);
    }
}
1
2
3
4
5
6
$users = App\User::popular()->active()->orderBy('created_at')->get();
$users = App\User::popular()->orWhere(function (Builder $query) {
    $query->active();
})->get();
// 允许高阶方法,不使用闭包方式
$users = App\User::popular()->orWhere->active()->get();

动态作用域

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 将查询作用域限制为仅包含给定类型的用户
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @param  mixed  $type
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }
}

// $users = App\User::ofType('admin')->get();

模型关联

定义关联

hasOne 一对一
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 获取用户的任务记录
     */
    public function task()
    {
        // 假设一个用户一条任务
        return $this->hasOne('App\Model\UserTask'); // 默认情况下 UserTask 模型中有 user_id
        // return $this->hasOne('App\Model\UserTask', 'foreign_key'); // 额外指定关系 key
        // return $this->hasOne('App\Model\UserTask', 'foreign_key', 'local_key'); // 额外指定 User key
    }
}
1
2
3
4
5
6
$model = User::find(1)->task;
/*
实际会执行两条 SQL,先查询出来结果,然后取到用户 ID 值再去查询 user_task 表的记录,limit 1 条记录
select * from `user` where `user`.`id` = ? limit 1
select * from `user_task` where `user_task`.`user_id` = ? and `user_task`.`user_id` is not null limit 1
*/
belongsTo 一对一反向
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 其实和一对一类似,只不过是通过 task 记录来找到用户的资料。

return $this->belongsTo('App\Model\User');

// 如果 task_user 中,user_id 不是外键,则需要指定foreign_key
// 取方法名然后加上 _id 当外键
return $this->belongsTo('App\Model\User', 'foreign_key'); 

// 如果父表不是 id 则指定 other_key
return $this->belongsTo('App\Model\User', 'foreign_key', 'other_key'); 
hasMany 一对多
1
2
// 一个用户多条任务场景
return $this->hasMany('App\Model\UserTask'); 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$model = User::find(1)->task;
/*
实际会执行两条 SQL,先查询出来结果,然后取到用户 ID 值再去查询 user_task 表的记录
select * from `user` where `user`.`id` = ? limit 1
select * from `user_task` where `user_task`.`user_id` = ? and `user_task`.`user_id` is not null
*/
$model = User::find(1)->task()->where('create_ymd', '20210927')->first();
/*
select * from `user` where `user`.`id` = ? limit 1
select * from `user_task` where `user_task`.`user_id` = ? and `user_task`.`user_id` is not null and `create_ymd` = ? limit 1
*/
belongsTo 一对多反向
1
2
3
4
5
6
7
// 只知道一条任务,需要查到该任务的人信息
return $this->belongsTo('App\Model\User');
return $this->belongsTo('App\Model\User', 'foreign_key');
return $this->belongsTo('App\Model\User', 'foreign_key', 'other_key');

// 通过一条任务记录,获取用户状态值
$userStatus = UserTask::find(1)->user->status;
belongsToMany 多对多

一个用户可以拥有多种角色,同时这些角色也被多个用户拥有。

定义这种关系需要三张表,users(用户表)、roles(角色表)、role_user(角色绑定关系表)该表命名由关联的两个模型按照字母顺序排序来,切该表包含了 user_id 和 role_id 字段。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 用户拥有的角色
     */
    public function roles()
    {
        return $this->belongsToMany('App\Role');
        // 指定关联表
        // return $this->belongsToMany('App\Role', 'role_user');
        // 指定关联表外键,第三个参数是次模型中的外键名,第四个参数是连接表中外键名。
        // return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
    }
}
1
2
3
4
5
6
7
8
// 获取该用户的所有角色
$user = App\User::find(1);

foreach ($user->roles as $role) {
    //
}

$roles = App\User::find(1)->roles()->orderBy('name')->get();
belongsToMany 多对多反向
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    /**
     * 拥有此角色的用户
     */
    public function users()
    {
        // 除了引入模型不同,其他都与正向连接相同
        return $this->belongsToMany('App\User');
    }
}
获取多对多中间表字段
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$user = App\User::find(1);
foreach ($user->roles as $role) {
    echo $role->pivot->created_at; // 获取关系绑定时间
}

// 中间表默认 pivot 对象值包含模型关联主键,需要额外字段需要关联时指出。
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');

// 中间表自动维护 created_at 和 updated_at 字段。
return $this->belongsToMany('App\Role')->withTimestamps();
自定义中间表模型

模型关联 |《Laravel 8.x》

多态关联

模型关联 |《Laravel 8.x》

一个模型中关联多个父级表,如图片表中的图片,可以属于用户,也可以属于某篇文章。

查询关联

模型关联 |《Laravel 8.x》

预加载

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$books = App\Book::with('author')->get();

foreach ($books as $book) {
    echo $book->author->name;
}
/*
select * from books
select * from authors where id in (1, 2, 3, 4, 5, ...)
*/

$books = App\Book::with(['author', 'publisher'])->get(); // 多关联
$books = App\Book::with('author.contacts')->get(); // 嵌套预加载
$books = App\Book::with('author:id,name')->get(); // 预加载指定参数列
$books = App\Book::without('author')->get(); // 去除预加载

protected $with = ['author']; // 模型中添加默认预加载

// 预加载添加约束
$users = App\User::with(['posts' => function ($query) {
    $query->where('title', 'like', '%first%');
}])->get();

$users = App\User::with(['posts' => function ($query) {
    $query->orderBy('created_at', 'desc');
}])->get();

插入更新关联模型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// 为指定文章添加一条新的评论
$comment = new App\Comment(['message' => 'A new comment.']);
$post = App\Post::find(1);
$post->comments()->save($comment);

// 为指定文章添加多条评论
$post = App\Post::find(1);
$post->comments()->saveMany([
    new App\Comment(['message' => 'A new comment.']),
    new App\Comment(['message' => 'Another comment.']),
]);

// 递归保存模型和关联数据
$post = App\Post::find(1);
$post->comments[0]->message = 'Message';
$post->comments[0]->author->name = 'Author Name';
$post->push();

// create 可以接受一个数组,需要配置批量赋值相关数据
$post = App\Post::find(1);
$comment = $post->comments()->create([
    'message' => 'A new comment.',
]);
$post = App\Post::find(1);
// 批量创建
$post->comments()->createMany([
    [
        'message' => 'A new comment.',
    ],
    [
        'message' => 'Another new comment.',
    ],
]);

// 更新 belongsTo 关联
$account = App\Account::find(10);
$user->account()->associate($account);
$user->save();
// 默认模型,用于查询不到关联模型的时候给出一个默认值
/**
 * 获取帖子的作者。
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault();
}
/**
 * 获取帖子的作者。
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault([
        'name' => 'Guest Author',
    ]);
}
/**
 * 获取帖子的作者。
 */
public function user()
{
    return $this->belongsTo('App\User')->withDefault(function ($user, $post) {
        $user->name = 'Guest Author';
    });
}

综合话题

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 查询原生 sql 执行语句
DB::connection('read')->enableQueryLog();
// 执行 sql 查询
dd(DB::connection('read')->getQueryLog());

\DB::enableQueryLog();
dd(\DB::getQueryLog());

\Illuminate\Support\Facades\DB::enableQueryLog();
dd(\Illuminate\Support\Facades\DB::getQueryLog());
1
2
3
4
5
// 缓存系统
$value = cache('key');

cache(['key' => 'value'], $seconds);
cache(['key' => 'value'], now()->addMinutes(10));

参考地址