99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

Eloquent ORM ―― 起步

2018-02-24 15:38 更新

Eloquent ORM —— 起步

1、簡介

Laravel自帶的Eloquent等操作。

在開始之前,確保在config/database.php文件中配置好了數(shù)據(jù)庫連接。更多關(guān)于數(shù)據(jù)庫配置的信息,請(qǐng)查看文檔。

2、定義模型

作為開始,讓我們創(chuàng)建一個(gè)Eloquent模型,模型通常位于app目錄下,你也可以將其放在其他可以被composer.json文件自動(dòng)加載的地方。所有Eloquent模型都繼承自Illuminate\Database\Eloquent\Model類。

創(chuàng)建模型實(shí)例最簡單的辦法就是使用Artisan命令make:model

php artisan make:model User

如果你想要在生成模型時(shí)生成數(shù)據(jù)庫遷移,可以使用--migration-m選項(xiàng):

php artisan make:model User --migration
php artisan make:model User -m

2.1 Eloquent模型約定

現(xiàn)在,讓我們來看一個(gè)Flight模型類例子,我們將用該類獲取和存取數(shù)據(jù)表flights中的信息:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model{
    //
}

2.1.1 表名

注意我們并沒有告訴Eloquent我們的Flight模型使用哪張表。默認(rèn)規(guī)則是模型類名的復(fù)數(shù)作為與其對(duì)應(yīng)的表名,除非在模型類中明確指定了其它名稱。所以,在本例中,Eloquent認(rèn)為Flight模型存儲(chǔ)記錄在flights表中。你也可以在模型中定義table屬性來指定自定義的表名:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model{
    /**
     * 關(guān)聯(lián)到模型的數(shù)據(jù)表
     *
     * @var string
     */
    protected $table = 'my_flights';
}

2.1.2?主鍵

Eloquent默認(rèn)每張表的主鍵名為id,你可以在模型類中定義一個(gè)$primaryKey屬性來覆蓋該約定。

2.1.3?時(shí)間戳

默認(rèn)情況下,Eloquent期望created_atupdated_at已經(jīng)存在于數(shù)據(jù)表中,如果你不想要這些Laravel自動(dòng)管理的列,在模型類中設(shè)置$timestamps屬性為false

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model{
    /**
     * 表明模型是否應(yīng)該被打上時(shí)間戳
     *
     * @var bool
     */
    public $timestamps = false;
}

如果你需要自定義時(shí)間戳格式,設(shè)置模型中的$dateFormat屬性。該屬性決定日期被如何存儲(chǔ)到數(shù)據(jù)庫中,以及模型被序列化為數(shù)組或JSON時(shí)日期的格式:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model{
    /**
     * 模型日期列的存儲(chǔ)格式
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

3、獲取多個(gè)模型

創(chuàng)建完模型及其關(guān)聯(lián)的數(shù)據(jù)表后,就要準(zhǔn)備從數(shù)據(jù)庫中獲取數(shù)據(jù)。將Eloquent模型看作功能強(qiáng)大的查詢構(gòu)建器,你可以使用它來流暢的查詢與其關(guān)聯(lián)的數(shù)據(jù)表。例如:

<?php

namespace App\Http\Controllers;

use App\Flight;
use App\Http\Controllers\Controller;

class FlightController extends Controller{
    /**
     * 顯示所有有效航班列表
     *
     * @return Response
     */
    public function index()
    {
        $flights = Flight::all();
        return view('flight.index', ['flights' => $flights]);
    }
}

3.1 訪問列值

如果你有一個(gè)Eloquent模型實(shí)例,可以通過訪問其相應(yīng)的屬性來訪問模型的列值。例如,讓我們循環(huán)查詢返回的每一個(gè)Flight實(shí)例并輸出name的值:

foreach ($flights as $flight) {
    echo $flight->name;
}

3.2 添加額外約束

Eloquent的all方法返回模型表的所有結(jié)果,由于每一個(gè)Eloquent模型都是一個(gè)查詢構(gòu)建器,你還可以添加約束條件到查詢,然后使用get方法獲取對(duì)應(yīng)結(jié)果:

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

注意:由于Eloquent模型本質(zhì)上就是查詢構(gòu)建器,你可以在Eloquent查詢中使用查詢構(gòu)建器的所有方法。

3.3 集合

對(duì)Eloquent中獲取多個(gè)結(jié)果的方法(比如allget)而言,其返回值是Illuminate\Database\Eloquent\Collection的一個(gè)實(shí)例,Collection類提供了多個(gè)有用的函數(shù)來處理Eloquent結(jié)果。當(dāng)然,你可以像操作數(shù)組一樣簡單循環(huán)這個(gè)集合:

foreach ($flights as $flight) {
    echo $flight->name;
}

3.4 組塊結(jié)果集

如果你需要處理成千上萬個(gè)Eloquent結(jié)果,可以使用chunk命令。chunk方法會(huì)獲取一個(gè)“組塊”的Eloquent模型,并將其填充到給定閉包進(jìn)行處理。使用chunk方法能夠在處理大量數(shù)據(jù)集合時(shí)有效減少內(nèi)存消耗:

Flight::chunk(200, function ($flights) {
    foreach ($flights as $flight) {
        //
    }
});

傳遞給該方法的第一個(gè)參數(shù)是你想要獲取的“組塊”數(shù)目,閉包作為第二個(gè)參數(shù)被調(diào)用用于處理每個(gè)從數(shù)據(jù)庫獲取的區(qū)塊數(shù)據(jù)。

4、獲取單個(gè)模型/聚合

當(dāng)然,除了從給定表中獲取所有記錄之外,還可以使用findfirst獲取單個(gè)記錄。這些方法返回單個(gè)模型實(shí)例而不是返回模型集合:

// 通過主鍵獲取模型...
$flight = App\Flight::find(1);
// 獲取匹配查詢條件的第一個(gè)模型...
$flight = App\Flight::where('active', 1)->first();

Not Found 異常

有時(shí)候你可能想要在模型找不到的時(shí)候拋出異常,這在路由或控制器中非常有用,findOrFailfirstOrFail方法會(huì)獲取查詢到的第一個(gè)結(jié)果。然而,如果沒有任何查詢結(jié)果,Illuminate\Database\Eloquent\ModelNotFoundException異常將會(huì)被拋出:

$model = App\Flight::findOrFail(1);
$model = App\Flight::where('legs', '>', 100)->firstOrFail();

如果異常沒有被捕獲,那么HTTP?404?響應(yīng)將會(huì)被發(fā)送給用戶,所以在使用這些方法的時(shí)候沒有必要對(duì)返回404響應(yīng)編寫明確的檢查:

Route::get('/api/flights/{id}', function ($id) {
    return App\Flight::findOrFail($id);
});

4.1 獲取聚合

當(dāng)然,你還可以使用查詢構(gòu)建器聚合方法,例如count、summax,以及其它查詢構(gòu)建器提供的聚合方法。這些方法返回計(jì)算后的結(jié)果而不是整個(gè)模型實(shí)例:

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

擴(kuò)展閱讀:實(shí)例教程 ——?ORM概述、模型定義及基本查詢

5、插入/更新模型

5.1?基本插入

想要在數(shù)據(jù)庫中插入新的記錄,只需創(chuàng)建一個(gè)新的模型實(shí)例,設(shè)置模型的屬性,然后調(diào)用save方法:

<?php

namespace App\Http\Controllers;

use App\Flight;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class FlightController extends Controller{
    /**
     * 創(chuàng)建一個(gè)新的航班實(shí)例
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        // Validate the request...

        $flight = new Flight;

        $flight->name = $request->name;

        $flight->save();
    }
}

在這個(gè)例子中,我們只是簡單分配HTTP請(qǐng)求中的name參數(shù)值給App\Flight模型實(shí)例的那么屬性,當(dāng)我們調(diào)用save方法時(shí),一條記錄將會(huì)被插入數(shù)據(jù)庫。created_atupdated_at時(shí)間戳在save方法被調(diào)用時(shí)會(huì)自動(dòng)被設(shè)置,所以沒必要手動(dòng)設(shè)置它們。

5.2 基本更新

save方法還可以用于更新數(shù)據(jù)庫中已存在的模型。要更新一個(gè)模型,應(yīng)該先獲取它,設(shè)置你想要更新的屬性,然后調(diào)用save方法。同樣,updated_at時(shí)間戳?xí)蛔詣?dòng)更新,所以沒必要手動(dòng)設(shè)置其值:

$flight = App\Flight::find(1);
$flight->name = 'New Flight Name';
$flight->save();

更新操作還可以同時(shí)修改給定查詢提供的多個(gè)模型實(shí)例,在本例中,所有有效且destination=San Diego的航班都被標(biāo)記為延遲:

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

update方法要求以數(shù)組形式傳遞鍵值對(duì)參數(shù),代表著數(shù)據(jù)表中應(yīng)該被更新的列。

5.3 批量賦值

還可以使用create方法保存一個(gè)新的模型。該方法返回被插入的模型實(shí)例。但是,在此之前,你需要指定模型的fillableguarded屬性,因?yàn)樗蠩loquent模型都通過批量賦值(Mass Assignment)進(jìn)行保護(hù)。

當(dāng)用戶通過HTTP請(qǐng)求傳遞一個(gè)不被期望的參數(shù)值時(shí)就會(huì)出現(xiàn)安全隱患,然后該參數(shù)以不被期望的方式修改數(shù)據(jù)庫中的列值。例如,惡意用戶通過HTTP請(qǐng)求發(fā)送一個(gè)is_admin參數(shù),然后該參數(shù)映射到模型的create方法,從而允許用戶將自己變成管理員。

所以,你應(yīng)該在模型中定義哪些屬性是可以進(jìn)行賦值的,使用模型上的$fillable屬性即可實(shí)現(xiàn)。例如,我們?cè)O(shè)置Flight模型上的name屬性可以被賦值:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model{
    /**
     * 可以被批量賦值的屬性.
     *
     * @var array
     */
    protected $fillable = ['name'];
}

設(shè)置完可以被賦值的屬性之后,我們就可以使用create方法在數(shù)據(jù)庫中插入一條新的記錄。create方法返回保存后的模型實(shí)例:

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

$fillable就像是可以被賦值屬性的“白名單”,還可以選擇使用$guarded。$guarded屬性包含你不想被賦值的屬性數(shù)組。所以不被包含在其中的屬性都是可以被賦值的,因此,$guarded方法就像“黑名單”。當(dāng)然,你只能同時(shí)使用其中一個(gè)——而不是一起使用:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model{
    /**
     * 不能被批量賦值的屬性
     *
     * @var array
     */
    protected $guarded = ['price'];
}

在這個(gè)例子中,除了$price之外的所有屬性都是可以被賦值的。

5.3.1 其它創(chuàng)建方法

還有其它兩種可以用來創(chuàng)建模型的方法:firstOrCreatefirstOrNew。firstOrCreate方法先嘗試通過給定列/值對(duì)在數(shù)據(jù)庫中查找記錄,如果沒有找到的話則通過給定屬性創(chuàng)建一個(gè)新的記錄。

firstOrNew方法和firstOrCreate方法一樣先嘗試在數(shù)據(jù)庫中查找匹配的記錄,如果沒有找到,則返回一個(gè)的模型實(shí)例。注意通過firstOrNew方法返回的模型實(shí)例并沒有持久化到數(shù)據(jù)庫中,你還需要調(diào)用save方法手動(dòng)持久化:

// 通過屬性獲取航班, 如果不存在則創(chuàng)建...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);
// 通過屬性獲取航班, 如果不存在初始化一個(gè)新的實(shí)例...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);

擴(kuò)展閱讀:實(shí)例教程 —— 模型創(chuàng)建、更新及批量賦值

6、刪除模型

要?jiǎng)h除一個(gè)模型,調(diào)用模型實(shí)例上的delete方法:

$flight = App\Flight::find(1);
$flight->delete();

6.1 通過主鍵刪除模型

在上面的例子中,我們?cè)谡{(diào)用delete方法之前從數(shù)據(jù)庫中獲取該模型,然而,如果你知道模型的主鍵的話,可以直接刪除而不需要獲取它:

App\Flight::destroy(1);
App\Flight::destroy([1, 2, 3]);
App\Flight::destroy(1, 2, 3);

6.2 通過查詢刪除模型

當(dāng)然,你還可以通過查詢刪除多個(gè)模型,在本例中,我們刪除所有被標(biāo)記為無效的航班:

$deletedRows = App\Flight::where('active', 0)->delete();

6.3?軟刪除

除了從數(shù)據(jù)庫刪除記錄外,Eloquent還可以對(duì)模型進(jìn)行“軟刪除”。當(dāng)模型被軟刪除后,它們并沒有真的從數(shù)據(jù)庫刪除,而是在模型上設(shè)置一個(gè)deleted_at屬性并插入數(shù)據(jù)庫,如果模型有一個(gè)非空deleted_at值,那么該模型已經(jīng)被軟刪除了。要啟用模型的軟刪除功能,可以使用模型上的Illuminate\Database\Eloquent\SoftDeletestrait并添加deleted_at列到$dates屬性:

<?php

namespace App;

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

class Flight extends Model{
    use SoftDeletes;

    /**
     * 應(yīng)該被調(diào)整為日期的屬性
     *
     * @var array
     */
    protected $dates = ['deleted_at'];
}

當(dāng)然,應(yīng)該添加deleted_at列到數(shù)據(jù)表。Laravel查詢構(gòu)建器包含一個(gè)幫助函數(shù)來創(chuàng)建該列:

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

現(xiàn)在,當(dāng)調(diào)用模型的delete方法時(shí),deleted_at列將被設(shè)置為當(dāng)前日期和時(shí)間,并且,當(dāng)查詢一個(gè)使用軟刪除的模型時(shí),被軟刪除的模型將會(huì)自動(dòng)從查詢結(jié)果中排除。

判斷給定模型實(shí)例是否被軟刪除,可以使用trashed方法:

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

6.4 查詢被軟刪除的模型

6.4.1 包含軟刪除模型

正如上面提到的,軟刪除模型將會(huì)自動(dòng)從查詢結(jié)果中排除,但是,如果你想要軟刪除模型出現(xiàn)在查詢結(jié)果中,可以使用withTrashed方法:

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

withTrashed方法也可以用于關(guān)聯(lián)查詢中:

$flight->history()->withTrashed()->get();

6.4.2 只獲取軟刪除模型

onlyTrashed方法之獲取軟刪除模型:

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

6.4.3 恢復(fù)軟刪除模型

有時(shí)候你希望恢復(fù)一個(gè)被軟刪除的模型,可以使用restore方法:

$flight->restore();

你還可以在查詢中使用restore方法來快速恢復(fù)多個(gè)模型:

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

withTrashed方法一樣,restore方法也可以用于關(guān)聯(lián)查詢

$flight->history()->restore();

6.4.4 永久刪除模型

有時(shí)候你真的需要從數(shù)據(jù)庫中刪除一個(gè)模型,可以使用forceDelete方法:

// 強(qiáng)制刪除單個(gè)模型實(shí)例...
$flight->forceDelete();
// 強(qiáng)制刪除所有關(guān)聯(lián)模型...
$flight->history()->forceDelete();

擴(kuò)展閱讀:實(shí)例教程 —— 模型刪除及軟刪除相關(guān)實(shí)現(xiàn)

7、查詢作用域

作用域允許你定義一個(gè)查詢條件的通用集合,這樣就可以在應(yīng)用中方便地復(fù)用。例如,你需要頻繁獲取最受歡迎的用戶,要定義一個(gè)作用域,只需要簡單的在Eloquent模型方法前加上一個(gè)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);
    }
}

7.1 使用查詢作用域

作用域被定義好了之后,就可以在查詢模型的時(shí)候調(diào)用作用域方法,但調(diào)用時(shí)不需要加上scope前綴,你甚至可以在同時(shí)調(diào)用多個(gè)作用域,例如:

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

7.2 動(dòng)態(tài)作用域

有時(shí)候你可能想要定義一個(gè)可以接收參數(shù)的作用域,你只需要將額外的參數(shù)添加到你的作用域即可。作用域參數(shù)應(yīng)該被定義在$query參數(shù)之后:

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

現(xiàn)在,你可以在調(diào)用作用域時(shí)傳遞參數(shù)了:

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

8、事件

Eloquent模型可以觸發(fā)事件,允許你在模型生命周期中的多個(gè)時(shí)間點(diǎn)調(diào)用如下這些方法:creating,?created,?updating,?updated,?saving,?saved,deleting,?deleted,?restoring,?restored。事件允許你在一個(gè)指定模型類每次保存或更新的時(shí)候執(zhí)行代碼。

8.1 基本使用

一個(gè)新模型被首次保存的時(shí)候,creatingcreated事件會(huì)被觸發(fā)。如果一個(gè)模型已經(jīng)在數(shù)據(jù)庫中存在并調(diào)用save方法,updating/updated事件會(huì)被觸發(fā)。

舉個(gè)例子,我們?cè)?a rel="external nofollow" target="_blank" target="_blank">服務(wù)提供者中定義一個(gè)Eloquent事件監(jiān)聽器,在事件監(jiān)聽器中,我們會(huì)調(diào)用給定模型的isValid方法,如果模型無效會(huì)返回false。如果從Eloquent事件監(jiān)聽器中返回false則取消save/update操作:

<?php

namespace App\Providers;

use App\User;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider{
    /**
     * 啟動(dòng)所有應(yīng)用服務(wù)
     *
     * @return void
     */
    public function boot()
    {
        User::creating(function ($user) {
            if ( ! $user->isValid()) {
                return false;
            }
        });
    }

    /**
     * 注冊(cè)服務(wù)提供者.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

擴(kuò)展閱讀:實(shí)例教程 —— Eloquent 查詢作用域 及模型事件

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)