iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 12
1
Modern Web

Laravel 6.0 初體驗!怎麼用最新的 laravel 架網站!系列 第 12

[Day 12] 實作物件之間的關聯!談 Laravel Model Relation

 今天我們來聊聊 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 然後重新建立資料庫。而是增加一個新的 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

Eloquent 語法

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 的兩個 Postsubject_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 修改現有的資料表結構,學到怎麼建立物件之間的關係,並且成功的透過關係取出了物件!

希望各位覺得今天的文章能有所收穫,我們明天見!


上一篇
[Day 11] 物件該怎麼使用!聊 Model 的 BREAD
下一篇
[Day 13] 幫文章加上標籤!聊多對多關係
系列文
Laravel 6.0 初體驗!怎麼用最新的 laravel 架網站!30

尚未有邦友留言

立即登入留言