Unity(C#)初心者・入門者向けチュートリアル ひよこのたまご

AndroidやiOS向けアプリを簡単に作れるゲーム開発環境Unity(ユニティ)の使い方を、チュートリアル方式で一緒に学びましょう!

【Laravel】Eloquentのリレーション① hasOne結合について

PHPバージョン:7.1.14
Laravelバージョン:5.7.9

前回まででLaravelのEloquentを使ったデータの登録・更新・削除を紹介しました!
今回からはEloquentのリレーションについてです!

データベースはテーブル同士が関連し合うことで
複雑なデータ構造を実現しています!
Laravelにはこのデータ同士の関連を表現する機能が標準で備わってします!
関連の種類には1対1・1対他・他対他とありますが、
今回は1対1を表すhasOne結合についてです!



hasOne結合

1対1の関係を表す、hasOne結合について。

2つのテーブルが関係する時、主テーブルと従テーブルに分けることができます。
主テーブルは参照される側で、中心となるテーブルです。
従テーブルは参照する側のテーブルで、主テーブルの外部キーを持ちます。

今回は主テーブルをauthors(著者)、従テーブルをarticles(記事)とします。
(便宜上、1人の著者に対して1つの記事という前提)

Migrationによるテーブル作成

まずはMigrationを使ってデータベースにauthorsテーブルを作成します。

$ php artisan make:migration create_authors_table

authorsテーブルを作成するためのMigrationファイルが出来ました。
ファイルを編集します。

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateAuthorsTable extends Migration
{
    public function up()
    {
        Schema::create('authors', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('authors');
    }
}

xxxx_xx_xx_xxxxxx_create_authors_table.php

デフォルトからstring型のnameカラムを追加したのみです。

続いて、以前作成したarticlesテーブルに
"author_id"という外部キーを追加します。
従テーブルに外部キーがあることで、hasOne結合を使うことができます。
まずはmigrationファイルから。

$php artisan make:migration add_columns_articles_table

migrationファイルが作成されました。
編集します。

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddColumnsArticlesTable extends Migration
{
    public function up()
    {
        Schema::table('articles', function(Blueprint $table) {
            $table->integer('author_id');
        });
    }

    public function down()
    {
        Schema::table('articles', function(Blueprint $table) {
            $table->dropColumn('author_id');
        });
    }
}

xxxx_xx_xx_xxxxxx_add_articles_table.php

既存のテーブルに項目を追加する時は
Schema::table()メソッドを使います。
第一引数がテーブル名、
第二引数がBlueprintを使った項目追加処理となります。
downメソッドの無名関数内ではdropColumnメソッドを使っています。
ロールバック時に指定したカラムは削除されます。

SeedingによるDBデータ作成

続いてSeedingによってDBデータを作成していきます。
まずは主テーブルであるauthorsテーブルのデータから。

$ php artisan make:seeder AuthorsSeeder

AuthorsSeederファイルが作成されました。
編集していきます。

<?php

use Illuminate\Database\Seeder;

class AuthorsSeeder extends Seeder
{
    public function run()
    {
        $param = [
            'name' => '一郎',
        ];
        DB::table('authors')->insert($param);

        $param = [
            'name' => '二郎',
        ];
        DB::table('authors')->insert($param);

        $param = [
            'name' => '三郎',
        ];
        DB::table('authors')->insert($param);
    }
}

database>seeds>AuthorsSeeder.php

名前のみ登録していきます。
id=1は一郎、id=2は二郎、id=3は三郎という形です。

続いて従テーブルであるarticlesテーブルです。
その前にMySQLに入り、articlesテーブルに入っているデータを全件削除します。

mysql> truncate table articles;

truncateコマンドでテーブルのデータを全件削除することが出来ます。

それでは以前作成したArticlesSeederを編集します。

<?php

use Illuminate\Database\Seeder;

class ArticlesSeeder extends Seeder
{
    public function run()
    {
        $param = [
            'title' => '【Laravel】Controllerの使い方',
            'body' => '今回はコントローラーの使い方についてです!',
// ***** 開始 *****
            'author_id' => 1,
// ***** 終了 *****
        ];
        DB::table('articles')->insert($param);

        $param = [
            'title' => '【Laravel】Viewの使い方',
            'body' => '今回はビューの使い方についてです!',
// ***** 開始 *****
            'author_id' => 2,
// ***** 終了 *****
        ];
        DB::table('articles')->insert($param);

        $param = [
            'title' => '【Laravel】 Modelの使い方',
            'body' => '今回はモデルの使い方についてです!',
// ***** 開始 *****
            'author_id' => 3,
// ***** 終了 *****
        ];
        DB::table('articles')->insert($param);
    }
}

database>seeds>ArticlesSeeder.php

外部キーであるauthor_idが新しく追加されました。

最後にDatabaseSeederファイルにAuthorSeederを追加してSeedingを実行します。

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->call(ArticlesSeeder::class);
// ***** 開始 *****
        $this->call(AuthorsSeeder::class);
// ***** 終了 *****
    }
}

database>seeds>DatabaseSeeder.php

コンソールにてSeedingを実行します。

$ php artisan db:seed
Seeding: ArticlesSeeder
Seeding: AuthorsSeeder
Database seeding completed successfully.

成功しました。

Modelの作成

続いてModelを作成していきます。
Authorモデルを作成します。

$ php artisan make:model Models/Author

Authorモデルが作成されました。
編集していきます。

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Author extends Model
{
    protected $guarded = array('id');

    public function article() {
        $this->hasOne('App\Models\Article');
    }
}

app>Models>Author.php

$guardedにより、idの外部変更を禁止しました。

今回メインとなるhasOneメソッドを使うのは主テーブルのモデル内です。
articleメソッドを作成し、その中にhasOneメソッドを記述します。
引数はモデルのパスです。

(従テーブルであるArticleモデルは特に変更点はありません。)

ArticleController編集

続いて ArticleControllerを編集していきます。
この中でhasOneメソッドを使います。

<?php
namespace App\Http\Controllers;

use App\Models\Author;
use App\Models\Article;
use Illuminate\Http\Request;

class ArticleController extends Controller
{
    function index() {
        $authors = Author::all();
        foreach($authors as $a) {
            dump( '著者:' . $a->name .
                ' タイトル:' . $a->article->title .
                ' 記事内容:'. $a->article->body);
        }
    }
}

app>Http>Controllers>ArticleController.php

Authorモデルから全てのAuthorデータを取得します。(一郎、二郎、三郎)
foreachで回しdumpをとっていきます。
hasOneメソッドが使われているarticleは、
メソッドの形ではなくプロパティの形で使用します。

結果

f:id:hiyotama:20181108175617p:plain

Authorのモデルデータから、
Articleの情報(titleとbody)を無事引き出すことができました!

今回はここまでです、ありがとうございました〜!