[Laravel] 16 - DB: Eloquent

前言


1、大綱

寫後端API,與數據庫打交道無疑是很重要的角色。php

PHP數據庫操做:從MySQL原生API到PDOhtml

PHP數據庫操做:使用ORMmysql

Ref: [PHP] 07 - Json, XML and MySQLlaravel

 

 

2、細節

SQL 教程sql

 

 

3、初識 Eloquent ORM

Eloquent ORM是Laravel框架使用的ORM。Laravel 的 Eloquent ORM 提供了更優雅的ActiveRecord 實現來和數據庫的互動。每一個數據庫表對應一個模型文件。數據庫

Goto: Eloquent: 入門【2.完整複習版本】後端

From: Eloquent ORM筆記【1.基礎篇】api

新增
# 新建了一條 id, name
$user = new User; $user->name = 'John'; $user->save(); $insertedId = $user->id;//從對象取得 id 屬性值

使用模型的 Create 方法 class User extends Model { protected $guarded = ['id', 'account_id'];  //黑名單,不會被更新 } // 創建一個用戶 $user = User::create(['name' => 'John']); // 以屬性找用戶 - 若沒有則新增並取得新的實例... $user = User::firstOrCreate(['name' => 'John']); // 以屬性找用戶 - 若沒有則創建新的實例... $user = User::firstOrNew(['name' => 'John']);


辨析
firstOrCreate:判斷以後直接入庫
firstOrNew :判斷以後還要作其餘業務流程,以後再入庫
$student=Student::firstOrNew([ 'vip_name'=>'mmm']); 
$student->save();   # 就是須要再單獨save一下

刪除
$this->where($where)->delete(); 或者 $user = User::find(1); $user->delete();


更新
return $this->where($where)->update($data); 或者 $user = User::find(1); $user->update($data);


查找
//取出全部記錄 - 能夠遍歷 $this->all()->toArray(); //取出一條數據 $one = $this->find('2'); return array( $one->id, $one->title, $one->content, ); //查找id=2的第一條數據 $this->where('id', 2)->first()->toArray(); //查找id>0的全部數據 $this->where('id', '>', '0')->get()->toArray();
  • For find(n), you retrieve a row based on the primary key which is 'n'.
  • For first(), you retrieve the first row among all rows that fit the where clauses.
  • For get()  , you retrieve all the rows that fit the where clauses. (Please note that loops are required to access all the rows or you will get some errors).
//降序排列 
$this->where('id', '>', '0')->orderBy('id', 'desc')->get()->toArray(); //降序排列,計數 
$this->where('id', '>', '0')->orderBy('id', 'desc')->count(); //從offset起始算起的limit條數據 
$this->where('id', '>', '0')->orderBy($order[0], $order[1])->skip($offset)->take($limit); //等同於
$this->where('id', '>', '0')->orderBy($order[0], $order[1])->offset($offset)->limit($limit);


條件類
//條件類 where('id', '>', '0') where('id', '>=', '0') where('id', '<', '0') where('id', '<=', '0') where('id', 'like', 'name%') whereIn($key, $array) whereNotIn($key, $array) whereBetween($key, $array) whereNotBetween($key, $array) orWhereIn($key, $array) orWhereNotIn($key, $array) orWhereBetween($key, $array) orWhereNotBetween($key, $array)


結果方法
//結果方法:Illuminate\Database\Query\Builder first()取第一個 get()取全部 all()取全部(無條件)


數學統計
//聚合方法 count() avg() sum() max() min()

 

 

  

Pure SQL


RDBMS 指關係型數據庫管理系統,全稱 Relational Database Management System。數組

(1). 登陸:mysql -u root -p 閉包

(2). phpMyAdmin建立數據庫,並導入.sql文件。

(3). 支持中文:set names utf8;

 

詳見:[MySQL] 01- Basic sql 

 

 

 

Eloquent: 入門


{tip} 因爲 Eloquent 模型是查詢構造器,所以你應當去閱讀全部 查詢構造器 中可用的方法。

 

1、模型

  • 生成模型、遷移文件
php artisan make:model User --migration php artisan make:model User -m
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;  # 全部的 Eloquent 模型都繼承自這個 class Flight extends Model
{
    // 用它從  數據表中取回與保存信息
}flights

 

  • 默認經常使用四屬性

[1] 表名

除非數據代表確地指定了其它名稱,不然將使用類的「蛇形名稱」、複數形式名稱來做爲數據表的名稱。自定義對應表名:

protected $table = 'my_flights';

 

 [2] 主鍵

設每一個數據表都有一個叫作 id 的主鍵字段。你也能夠定義一個 $primaryKey 屬性來重寫這個約定。

默認是遞增;不然,必須在你的模型 public $incrementing=false

 

[3] 時間戳

默認狀況下,Eloquent 會認爲在你的數據庫表有 created_at 和 updated_at 字段。

若是你不但願讓 Eloquent 來自動維護這兩個字段,可在模型內將 $timestamps=false

決定了日期應如何在數據庫中存儲,以及當模型被序列化成數組或 JSON 格式 protected $dateFormat = 'U';

 

[4] 鏈接數據庫 

默認狀況下,全部的 Eloquent 模型會使用應用程序中默認的數據庫鏈接設置。

若是你想爲模型指定不一樣的鏈接,可使用 protected $connection = 'connection-name'; 

 

[5] 經過模型獲取結果

$flights = App\Flight::where('active', 1) ->orderBy('name', 'desc') ->take(10) ->get();

 

  • 模型建立與刪除

詳見:"3、初識 Eloquent ORM"

補充:軟刪除

模型上設置一個 deleted_at 屬性並將其添加到數據庫。若是模型有一個非空值 deleted_at,表明模型已經被軟刪除了。

[1] 設置字段

當模型被軟刪除時,它們並不會真的從數據庫中被移除。而是會在模型上設置一個 deleted_at 屬性並將其添加到數據庫。

若是模型有一個非空值 deleted_at,表明模型已經被軟刪除了。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Flight extends Model
{
    use SoftDeletes;

    /**
     * 須要被轉換成日期的屬性。
* 添加  字段到你的  屬性。 * * @var array
*/ protected $dates = ['deleted_at']; }deleted_at$dates

 

[2] 添加 deleted_at 字段到數據表 

Schema::table('flights', function ($table) { $table->softDeletes(); });

當查詢有啓用軟刪除的模型時,被軟刪除的模型將會自動從全部查詢結果中排除。

 

[3] 查詢 deleted_at 字段

確認指定的模型實例是否已經被軟刪除,可使用 trashed 方法:

if ($flight->trashed()) { // }

 

[4] 查詢捎帶上 '軟刪除‘ 集合

$flights = App\Flight::withTrashed() ->where('account_id', 1) ->get();

 

[5] 只查詢 ‘軟刪除’ 集合

$flights = App\Flight::onlyTrashed() ->where('airline_id', 1) ->get();

 

[6] 恢復 '軟刪除'

$flight->restore(); App\Flight::withTrashed() ->where('airline_id', 1) ->restore();

 

[7] 永久地刪除模型

// 強制刪除單個模型實例...
$flight->forceDelete(); // 強制刪除全部相關模型...
$flight->history()->forceDelete();

 

 

2、集合

Collection 類提供 多種輔助函數 來處理你的 Eloquent 結果。 

 

  • 遍歷 Chunk & Cursor 

[Chunk]

It will "paginate" your query, this way you use less memory. (1) Uses less memory (2) It takes longer

public function getData() { Contact::chunk(1000, function ($contacts) { foreach ($contacts as $contact) { //rest of your code...
 } }); }

[Cursor]

You will use PHP Generators to search your query items one by one. (1) It takes less time (2) Uses more memory

public function getData() { foreach (Contact::cursor() as $contact) { //rest of your code...
 } }

 

  • 返回指定行
// 取回符合查詢限制的第一個模型 ...
$flight  = App\Flight::where('active', 1)->first(); $flights = App\Flight::find([1, 2, 3]);

  

  • ‘未找到’ 處理
$model = App\Flight::findOrFail(1); $model = App\Flight::where('legs', '>', 100)->firstOrFail(); 
// 用法示範 Route
::get('/api/flights/{id}', function ($id) {
  return App\Flight::findOrFail($id);
});

 

  • 聚合函數

可使用 countsummax和其它 查詢構造器 提供的 聚合函數

這些方法會返回適當的標量值,而不是一個完整的模型實例

$count = App\Flight::where('active', 1)->count(); $max   = App\Flight::where('active', 1)->max('price');

 

 

3、控制器

  • 添加一條記錄

自動完成了例如對時間戳的記錄。

<?php namespace App\Http\Controllers; use App\Flight; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class FlightController extends Controller { /** * 建立一個新的航班實例。 * * @param Request $request * @return Response */
    public function store(Request $request) {
        $flight = new Flight;
$flight->name = $request->name; $flight->save(); } }

 

  • 更新 & 批量更新
$flight = App\Flight::find(1); $flight->name = 'New Flight Name'; $flight->save();

兩個where並列條件,而後更新字段:delayed

App\Flight::where('active', 1) ->where('destination', 'San Diego') ->update(['delayed' => 1]);

{note} 當經過「Eloquent」批量更新時,savedupdated模型事件將不會被更新後的模型代替。這是由於批量更新時,模型歷來沒有被取回。

 

  • 批量賦值

注意批量賦值是有風險的,全部的 Eloquent 模型都針對批量賦值(Mass-Assignment)作了保護。

方案:$fillable 做爲一個能夠被批量賦值的屬性「白名單」;$guarded 是「黑名單」,設置爲空表明大門敞開。 

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * 能夠被批量賦值的屬性。
* 使  模型的  屬性能夠被批量賦值 * * @var array */
protected $fillable = ['name']; }Flightname

賦值:

$flight = App\Flight::create(['name' => 'Flight 10']); $flight->fill(['name' => 'Flight 22']);

 

 

4、查詢做用域

  • 編寫 全局做用域

自定義全局做用域很簡單,首先定義一個實現 Illuminate\Database\Eloquent\Scope 接口的類,該接口要求你實現一個方法:apply

<?php namespace App\Scopes; use Illuminate\Database\Eloquent\Scope; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; class AgeScope implements Scope { /** * 應用做用域 * * @param \Illuminate\Database\Eloquent\Builder $builder * @param \Illuminate\Database\Eloquent\Model $model * @return void */
    public function apply(Builder $builder, Model $model) { return $builder->where('age', '>', 200); # select * from `users` where `age` > 200 } }

{tip} Laravel 沒有規定你須要把這些類放置於哪一個文件夾,你能夠自由在 app 文件夾下建立 Scopes 文件夾來存放。

 

  • 應用全局做用域
<?php

namespace App;

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

class User extends Model
{
    /**
     * 數據模型的啓動方法
     *
     * @return void
     */
    protected static function boot()                    # 須要重寫給定模型的 boot 方法
    {
        parent::boot();
        static::addGlobalScope(new AgeScope);            # 並使用  方法
    }
}addGlobalScope

添加做用域後,若是使用 User::all() 查詢則會生成以下SQL語句:select * from `users` where `age` > 200

 

  • 匿名的全局做用域

Eloquent 還容許咱們使用閉包定義全局做用域,這在實現簡單做用域的時候特別有用,這樣的話,咱們就不必定義一個單獨的類。

<?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); }); } }

 

  • 移除 全局做用域
User::withoutGlobalScope('age')->get(); User::withoutGlobalScope(AgeScope::class)->get(); // 移除多個
User::withoutGlobalScopes([FirstScope::class, SecondScope::class])->get();

  

  • 本地做用域

本地做用域容許咱們定義通用的約束集合以便在應用中複用。

例如,你可能常常須要獲取最受歡迎的用戶,要定義這樣的一個做用域,只需在對應 Eloquent 模型方法前加上一個 scope 前綴,做用域老是返回查詢構建器:

<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 限制查詢只包括受歡迎的用戶。 * * @return \Illuminate\Database\Eloquent\Builder */
    public function scopePopular($query) { return $query->where('votes', '>', 100); } /** * 限制查詢只包括活躍的用戶。 * * @return \Illuminate\Database\Eloquent\Builder */
    public function scopeActive($query) { return $query->where('active', 1); } }

  

Then, 利用查詢範圍

一旦定義了範圍,則能夠在查詢模型時調用範圍方法。在進行方法調用時不須要加上 scope 前綴。你甚至能夠鏈式調用不一樣的範圍,如:

$users = App\User::popular()->active()->orderBy('created_at')->get();

    

  • 動態範圍

定義一個可接受參數的範圍。

這時只需給你的範圍加上額外的參數便可。範圍參數應該被定義在 $query 參數以後:

<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 限制查詢只包括指定類型的用戶。 * * @return \Illuminate\Database\Eloquent\Builder */
    public function scopeOfType($query, $type) { return $query->where('type', $type); } }

在範圍調用時傳遞參數:

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

 

  

5、事件

  • 模型的事件映射

事件讓你每當有特定的模型類在數據庫保存或更新時,執行代碼。

Eloquent 模型會觸發許多事件,讓你在模型的生命週期多個時間點進行監控:creatingcreatedupdatingupdatedsavingsaveddeletingdeletedrestoringrestored。

 

舉例子:

當一個新模型被初次保存將會觸發 creating 以及 created 事件

若是一個模型已經存在於數據庫且調用了 save 方法,將會觸發 updating 和 updated 事件

這兩種狀況下都會觸發 saving 和 saved事件

<?php namespace App; use App\Events\UserSaved; use App\Events\UserDeleted; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * 模型的事件映射。 * * @var array */
    protected $events = [ 'saved'   => UserSaved::class,
        'deleted' => UserDeleted::class, ]; }

  

  • 觀察者

若是你在一個給定的模型中監聽許多事件,您可使用觀察者將全部監聽器變成一個類

觀察者類裏的方法名應該反映Eloquent想監聽的事件。 每種方法接收 model 做爲其惟一的參數。

Laravel不包括觀察者默認目錄,因此你能夠建立任何你喜歡你的目錄來存放:

<?php namespace App\Observers; use App\User; class UserObserver { /** * 監聽用戶建立的事件。 * * @param User $user * @return void */
    public function created(User $user) { //  } /** * 監聽用戶刪除事件。 * * @param User $user * @return void */
    public function deleting(User $user) { //  } }

AppServiceProvider註冊觀察者

<?php namespace App\Providers; use App\User; use App\Observers\UserObserver; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * 運行全部應用. * * @return void */
    public function boot() { User::observe(UserObserver::class); } /** * 註冊服務提供. * * @return void */
    public function register() { //  } }

  

Ref: Laravel 數據庫之:數據庫請求構建器【往後繼續補充】

相關文章
相關標籤/搜索