今天我們來聊聊 Laravel 操作資料庫一個很重要的特性:物件之間的關聯。
當我們在設計物件的時候,很多的時候物件和物件之間是有關聯性的。這也是在設計資料庫架構時常常需要考慮的地方。
舉例來說,以我們前面的留言板的 Post
物件和 Subject
物件為例,
Post
可以有一個 Subject
Subject
可以對應多個 Post
所以我們可以知道,他們之間是一對多這層關聯。
下面介紹怎麼利用 Laravel 的語法,來處理這兩個物件的關聯。
首先,以資料面上來說,讀者可能會注意到,勢必要有一個地方紀錄哪篇留言對應哪個主題。這樣新增主題時才有地方紀錄。
以我們的需求來說,對應的地方會在 posts
資料表裡面,加上對應的 Subject
id。而不是採取在 subjects
資料表裡面加上 Post
id 的方式,因為這樣會導致需要紀錄多個 id,甚至可能會有個數限制等等的問題。
方便的是,Laravel 這方面做得非常簡單,只需要在 posts
裡面加上 subject_id
這個欄位,Laravel 就能自動知道這是對應 Subject
物件的 id,並且要在 subjects
資料表裡面搜尋對應的資料。
很方便吧!我們來嘗試一下。
為了不更動我們前面所做的資料結構,我們這裡不是修改之前的 migration 然後重新建立資料庫。而是增加一個新的 migration,來修改現有的資料表:
$ php artisan make:migration add_subject_id_to_posts_table
Created Migration: 2019_09_14_140611_add_subject_id_to_posts_table
我們來看看程式碼:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddSubjectIdToPostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('posts', function (Blueprint $table) {
//
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('posts', function (Blueprint $table) {
//
});
}
}
Laravel 依舊很方便地從我們的語法中,分析出我們想要修改 posts
資料表,並幫我們填入程式碼。
我們修改一下程式,讓這個 migration 加入 subject_id
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddSubjectIdToPostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->bigInteger('subject_id')->after('content');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->dropColumn('subject_id');
});
}
}
這樣就好囉!我們跟之前一樣執行 php artisan migrate
,成功的話,應該就可以在資料庫中看到 posts
資料表內,在 content
的後面多了一個 subject_id
Laravel 的 Eloquent 裡面,可以透過 $this->hasMany()
這個函式,來宣告該物件可以有多個某物件。
我們在 Subjects
裡面,加上
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function posts()
{
return $this->hasMany(Post::class);
}
在 Post
裡面,我們則加上 $this->belongsTo()
這個函式,來宣告該物件可以屬於某一個物件
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function subject()
{
return $this->belongsTo(Subject::class);
}
這樣就好了。
是不是簡單的很不可思議?我們來嘗試看看怎麼使用這個關聯。
首先,我們在資料庫建立 id
為 1 和 2 的兩個 Subject
然後在 posts
裡面,將 id
為 1 和 2 的兩個 Post
,subject_id
設置為 1,另一個設置為 2。
然後我們使用前面的測試路徑,來取出 subject_id
為 1 的 Post
:
Route::get('/test', function(){
$subject = Subject::find(1);
$posts = $subject->posts;
return $posts;
});
成功的話,應該會看到:
[
{
id: 1,
content: "Laravel demo 6.0 day 11 test",
created_at: null,
updated_at: "2019-09-13 09:20:51",
subject_id: 1
},
{
id: 2,
content: "Laravel demo 6.0 day 11 test",
created_at: null,
updated_at: null,
subject_id: 1
}
]
就這樣!利用 Laravel 幫我們預先做好的很多判斷,我們成功的用很短的程式,就建立起物件之間的關係了!
今天總結一下我們學到的東西。我們學到怎麼用 migration 修改現有的資料表結構,學到怎麼建立物件之間的關係,並且成功的透過關係取出了物件!
希望各位覺得今天的文章能有所收穫,我們明天見!