Eloquent ORM

Object Relational Mapping (ORM) 是一種物件和關聯對映的技術。物件指的是物件導向程式語言中的物件,關聯則是關聯式資料庫,ORM 是一個中間轉換的角色,讓原本必須直接接觸關聯式資料庫的部份,轉換成相對映的物件,這樣就能使用物件來操控資料庫,在開發上會比較直覺,也比較容易使用。在 Laravel 框架中,使用 Eloquent ORM。

基本使用

定義模型 (Model)

Model 預設放在 app/models 目錄下。例如:app/models/Post.php,內容如下:

<?php
class Post extends Eloquent{}

在 Eloquent ORM 中,會自動以 Model 的類別名稱的小寫、複數名稱去找尋對應的資料表,所以 Post 的對應資料表就會是 posts 。

當然,你也可以自行指定資料表的名稱:

<?php
class Post extends Eloquent{
protected $table = "post";
}

Eloquent ORM 也假設每個資料表都有一個 primary key 的欄位叫做 id。當然也可以自行定義 primaryKey 屬性去改變預設的名稱,例如:

protected $primaryKey = "myid";

當你的 Model 建立時,Eloquent ORM 會自動幫你加入兩個欄位 updated_at 和 created_at,這兩個欄位會記錄該筆紀錄的更新時間及建立時間(第一次建立時兩者時間相同)。如果你沒有這個需要,可以告訴 Eloquent ORM 不要建立,將 $timestamps 屬性設為 false 即可:

public $timestamps = false;

取得整個資料表的資料

$posts = Post::all();

回傳陣列資料。Post 是該 Model 類別的名稱,all() 方法會回傳整個資料表的資料。

透過 Primary key 取得一筆紀錄

$post = Post::find(1);

使用 find() 方法,及參數為 id 的值,回傳 Post 物件。

註:在前一節 Query Builder 中所介紹的方法全都可以在 Eloquent ORM 中找到相同名稱的方法。它們分屬 Illuminate/Database/Query/Builder.php 及 Illuminate/Database/Eloquent/Builder.php 兩個類別,都有實作同樣的方法名稱。

透過 Primary key 取得一筆紀錄,或丟出例外

假如你需要在找不到資料時顯示 404 等的錯誤頁面,可以讓 Eloquent ORM 丟出例外,使用

$post = Post::findOrFail(1);

或

$post = Post::where('title', '=', 'abc')->firstOrFail();

findOrFail() 和 firstOrFail() 方法會丟出例外。那丟出的例外要由誰接手處理呢?打開 app/start/global.php 檔案,在最前面加入:

<?php
use Illuminate\Database\Eloquent\ModelNotFoundException;

表示要用到 ModelNotFoundException 這個例外類別。

接著在 Application Error Handler (找註解可看到) 區塊中原本的 App::error 之後加上:

App::error(function(ModelNotFoundException $e)
{
return Response::make('Not Found', 404);
});

這樣 Eloquent ORM 丟出的例外就會以 404 的錯誤頁面 (這裡顯示 'Not Found' 文字)來表示。

如果要自訂錯誤頁面,可以改成

return Response::view('errors.missing', array(), 404);

然後建立 404 的 view,app/views/errors/missing.blade.php:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>404</title>
</head>
<body>
<span style="font-size:50em; color:#e2e2e2;">404</span>
</body>
</html>

條件查詢

使用 where 來做條件查詢,

$posts = Post::where('id', '>', 1)->get();

傳回陣列。用法都和之前介紹的 Query Builder 均相同。

大量指派 (mass-assignment)

基於安全的考量,Eloquent ORM 預設是禁止大量指派資料到資料庫中,例如使用迴圈來一次新增很多的資料。如果你有大量指派的需求,必須使用 fillable 屬性:

<?php
​
class Post extends Eloquent {
protected $fillable = ['title', 'content'];
}

你所指定的 title 及 content 這兩個欄位就允許大量指派。

fillable 如果是白名單,那相反的也可指定某個欄位"不允許"大量指派的黑名單,透過 guarded 屬性:

protected $guarded = ['id'];

這樣 'id' 這個欄位就不允許大量指派。如果要保護所有欄位都不能被大量指派:

protected $guarded = array('*');

Insert, Update, Delete

Insert (新增)

new 一個 Model 所代表的類別,就是預備新增一筆資料:

$post = new Post;
$post->title = 'Hello~~';
$post->save();

在新增資料後可以立即取得該筆資料的 id:

$postId = $post->id;

你也可以使用 Create 方法來新增資料:

$post = Post::create(['title' => 'Hello~~'));

前提是,你的 Model 必須設定 fillable 或 guarded 其中一個屬性。

Update (更新)

先找到要更新的資料才能更新:

$post = Post::find(1);
$post->title = 'Hi~~';
$post->save();

如果你有使用 timestamps 欄位,而且你只想更新它的時間 (updated_at 欄位),你可以"碰一下":

$post->touch();

刪除 (Delete)

$post = Post::find(1);
$post->delete();

或使用 destroy 方法:

Post::destroy(1);
Post::destroy(1,2,3);

參數是 id。