Laravel 模型讀操做

配套視頻地址 https://www.bilibili.com/video/av70545323?p=6

建立模型

php artisan make:model User       // 默認對應的表是 users
php artisan make:model AbCd       // 默認對應的表是 ab_cds
/**
規則:
    1. 除第一個大寫字母,其餘大寫字母前都加上下劃線
    2. 全部的大寫字母改爲小寫
    3. 末尾加 s
*/

模型之讀

\App\User::all();                          // 返回包含全部對象的集合
\App\User::where('name', 'John')->first(); // 返回對象
\App\User::where('id', 1)->value('name');   // 返回值,例如 'leon'
\App\User::find(3);                        // 返回主鍵等於 3 的對象
\App\User::find([1, 2]);                   // 返回主鍵等於 1 和 2 的對象的集合
\App\User::pluck('age');                   // 返回包含字段值的集合
\App\User::pluck('age', 'id');             // 返回關聯集合 id => age,pluck 最多 2 個參數
\App\User::count();                        // 返回記錄總數
\App\User::max('id');                      // 返回數字,庫沒有任何記錄返回 null
\App\User::min('id');                      // 返回數字,庫沒有任何記錄返回 null
\App\User::avg('age');                     // 返回數字,庫沒有任何記錄返回 null,同名 averge
\App\User::sum('salary');                  // 返回數字,庫沒有任何記錄返回 0
where
where('votes', '=', 100)
where('votes', 100)
where('votes', '>=', 100)
where('votes', '<>', 100)
where('name', 'like', 'T%')
where([
    ['status', '=', '1'],
    ['subscribed', '<>', '1'],
])
where('votes', '>', 100)->orWhere('name', 'John')
whereBetween('votes', [1, 100])           // 包含了 1 和 100
whereNotBetween('votes', [1, 100])
whereIn('id', [1, 2, 3])
whereNotIn('id', [1, 2, 3])
whereNull('last_name')
whereNotNull('updated_at')
whereDate('created_at', '2016-12-31')   // where date(created_at) = '2016-12-31')
whereMonth('created_at', '12')
whereDay('created_at', '31')
whereYear('created_at', '2016')
whereTime('created_at', '=', '11:20:45')
whereColumn('first_name', 'last_name')        // 判斷兩個字段 相等
whereColumn('updated_at', '>', 'created_at')

whereColumn([
    ['first_name', '=', 'last_name'],
    ['updated_at', '>', 'created_at']
])

where('finalized', 1)->exists();      // 返回 true 或者 false
// select exists(select * from `xxx` where `finalized` = 1) as `exists`
where('finalized', 1)->doesntExist();
// 運行的 SQL 和上面的同樣,Laravel 把運行結果取反就達成目的了
    
where('name', '=', 'John')
->orWhere(function ($query) {  // 傳入閉包進 orWhere,避免全局 scope 產生不良影響
    $query->where('votes', '>', 100)
          ->where('title', '<>', 'Admin');
})
// where `name` = John or (`votes` > 100 and `title` <> Admin)

whereExists(function ($query) {
    $query->selectRaw(1)
          ->from('orders')
          ->whereRaw('orders.user_id = users.id');
})   
// where exists ( select 1 from orders where orders.user_id = users.id )
  
->whereRaw('price > IF(state = "TX", ?, 100)', [200])->get();
// IF 用法:IF(expr1,expr2,expr3)   
// 若是 (expr1 <> 0 and expr1 <> NULL),那麼 expr1 就是 true。
json
$users = \App\User::where('options->language', 'en')
                ->get();
// select * from `users` where json_unquote(json_extract(`options`, '$."language"')) = 'en'

$users = \App\User::where('preferences->dining->meal', 'salad')
                ->get();
// select * from `users` where json_unquote(json_extract(`preferences`, '$."dining"."meal"')) = 'salad'

$users = \App\User::whereJsonLength('options->languages', 0)
                ->get();
// select * from `users` where json_length(`options`, '$."languages"') = 0

$users = \App\User::whereJsonLength('options->languages', '>', 1)
                ->get();
// select * from `users` where json_length(`options`, '$."languages"') > 1
\App\User::orderBy('date')->where('active', false)->chunk(100, function ($users) {  // 取每 100 個一組
    foreach ($users as $user) {
        // ...
        // return false;                                           // 隨時能夠退出
    }
});      
// select * from `users` where `active` = 0 order by `date` asc limit 3 offset 0
// select * from `users` where `active` = 0 order by `date` asc limit 3 offset 3
// 注意,laravel 把 false 轉化成了 0


// 不會出現 chunk 結束後,還有不少記錄沒被處理的狀況
\App\User::where('active', false)->orderBy('date')
    ->chunkById(100, function ($users) {
        foreach ($users as $user) {
            \App\User::where('id', $user->id)
                ->update(['active' => true]);
        }
    });
// select * from `users` where `active` = 0 order by `date` asc, `id` asc limit 3
// select * from `users` where `active` = 0 and `id` > 3 order by `date` asc, `id` asc limit 3
select
$users = \App\User::select('name', 'email as user_email')->get();

$users = \App\User::distinct()->get();
// select distinct * from `users1`

$query = \App\User::select('name');
$users = $query->addSelect('age')->get();
// select `name`, `age` from `users`
->selectRaw('department, SUM(price) as total_sales')
->groupBy('department')
->havingRaw('SUM(price) > ?', [2500])
->orderByRaw('updated_at - created_at DESC')
->get();
// select department, SUM(price) as total_sales from `destinations` group by `department` having SUM(price) > 2500 order by updated_at - created_at DESC
join 和 union
# inner join
->join('contacts', 'users.id', '=', 'contacts.user_id')
->join('orders', 'users.id', '=', 'orders.user_id')
->select('users.*', 'contacts.phone', 'orders.price')
->get();

# left join

->leftJoin('posts', 'users.id', '=', 'posts.user_id')
->get();

# right join

->rightJoin('posts', 'users.id', '=', 'posts.user_id')
->get();

# cross join

->crossJoin('colours')
->get();

# 高級 join

->join('contacts', function ($join) {
    $join->on('users.id', '=', 'contacts.user_id')->orOn('users.pid', '=', 'contacts.pid');
})
->get();
// select * from `users` 
//     inner join 
// `contacts` 
//     on `users`.`id` = `contacts`.`user_id` or `users`.`pid` = `contacts`.`pid`


->join('contacts', function ($join) {
    $join->on('users.id', '=', 'contacts.user_id')
         ->where('contacts.user_id', '>', 5);
})
->get();
// select * from `users` inner join `contacts` 
//     on
// `users`.`id` = `contacts`.`user_id` and `contacts`.`user_id` > 5


# union
$first = App\User::whereNull('first_name');

$users = App\Student::whereNull('last_name')
            ->union($first)
            ->get();
// (select * from `students` where `last_name` is null) union (select * from `users` where `first_name` is null)

# unionAll 和 union 參數同樣
// unionAll 不會去除重複值
排序、分組和分頁
orderBy('name', 'desc')

latest()                // === orderBy('created_at', 'desc')

inRandomOrder()
// order by RAND()

->groupBy('account_id')->having('account_id', '>', 100)

->groupBy('site', 'qianjinyike.com')->having('account_id', '>', 100)
    
skip(10)->take(5)        // 等價於 offset(10)->limit(5)
// limit 5 offset 10
分支執行 sql
// $role 有值纔會執行閉包
$role = $request->input('role');

$users = \App\User::when($role, function ($query) use ($role) {
                    return $query->where('role_id', $role);
                })
                ->get();

// $role 有值執行第一個閉包,不然執行第二個閉包
$sortBy = null;
$users = \App\User::when($sortBy, function ($query, $sortBy) {
                    return $query->orderBy($sortBy);
                }, function ($query) {
                    return $query->orderBy('name');
                })
                ->get();
刷新模型
$flight = App\Flight::where('number', 'FR 900')->first();
$freshFlight = $flight->fresh();  // 去數據庫裏面從新取了一次

$flight = App\Flight::where('number', 'FR 900')->first();
$flight->number = 'FR 456';
$flight->refresh();
$flight->number; // "FR 900"
遊標

cursor 容許你使用遊標來遍歷數據庫數據,一次只執行單個查詢。在處理大數據量請求時 cursor 方法能夠大幅度減小內存的使用:php

foreach (Flight::where(&#039;foo&#039;, &#039;bar&#039;)-&gt;cursor() as $flight) {
    //
}

$users = App\User::cursor()-&gt;filter(function ($user) {
    return $user-&gt;id &gt; 500;
});
高級子查詢
Destination::addSelect(['last_flight' => Flight::select('name')
    ->whereColumn('destination_id', 'destinations.id')
    ->orderBy('arrived_at', 'desc')
    ->latest()
    ->limit(1)
])->get();
// select `destinations`.*, (select `name` from `flights` where `destination_id` = `destinations`.`id` order by `arrived_at` desc, `created_at` desc limit 1) as `last_flight` from `destinations`
未找到異常

findOrFail 以及 firstOrFail 方法會取回查詢的第一個結果。若是沒有找到相應結果,則會拋出一個 Illuminate\Database\Eloquent\ModelNotFoundExceptionlaravel

$model = App\Flight::findOrFail(1);

$model = App\Flight::where(&#039;legs&#039;, &#039;&gt;&#039;, 100)-&gt;firstOrFail();
全局做用域
// 能夠自由在  app 文件夾下建立 Scopes 文件夾來存放
&lt;?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class AgeScope implements Scope {
    public function apply(Builder $builder, Model $model)
    {
        $builder-&gt;where(&#039;age&#039;, &#039;&gt;&#039;, 200);
    }   // 使用 addSelect 而不是 select,能夠避免覆蓋
}

// 須要重寫給定模型的 boot 方法並使用 addGlobalScope 方法
&lt;?php
namespace App;
use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
    protected static function boot() {
        parent::boot();

        static::addGlobalScope(new AgeScope);
    }
}
# 添加做用域後,若是使用 User::all() 查詢則會生成以下SQL語句:
select * from `users` where `age` > 200
匿名全局做用域(專門用來處理單個模型)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class User extends Model {
    protected static function boot() {
        parent::boot();

        static::addGlobalScope('age', function (Builder $builder) {
            $builder->where('age', '>', 200);
        });
    }
}
移除全局做用域
# 咱們還能夠經過如下方式,利用 age 標識符來移除全局做用:
User::withoutGlobalScope('age')->get();

# 移除指定全局做用域
User::withoutGlobalScope(AgeScope::class)->get();

# 移除幾個或所有全局做用域
User::withoutGlobalScopes([
    FirstScope::class, SecondScope::class
])->get();

# 移除全部全局做用域
User::withoutGlobalScopes()->get();
本地做用域
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model {

    public function scopePopular($query) {
        return $query->where('votes', '>', 100);
    }

    public function scopeActive($query) {
        return $query->where('active', 1);
    }
}
# 在進行方法調用時不須要加上 scope 前綴
$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();
動態範圍
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }
}

如今,你能夠在範圍調用時傳遞參數:sql

$users = App\User::ofType('admin')->get();
相關文章
相關標籤/搜索