【Laravel】Model(モデル)の作成方法と何を書くかを考える

※本サイトはアフィリエイトリンクを掲載しています。
Laravel

LaravelのModel(モデル)について

LaravelのModelは、データベースのデータ操作をするために作成します。

Modelを使用することで、例えばデータの取得や追加・更新・データの変換などを行うことができます。

基本的には、テーブルとモデルは1対1になります。
データベースの1つのテーブルにつき、ひとつのモデルを用意します。

 

Model(モデル)を作成する

artisanコマンドを使用することで、Modelを作成することができます。

今回は例としてMemberモデルを作成します。

php artisan make:model Member

実行結果キャプチャ

Modelはapp/Models/ディレクトリに作成されます。

 

Modelの命名規則について

Modelの命名規則はキャメルケースの単数形となります。

キャメルケースとは複数単語でModel名を構成する場合、各単語の先頭文字を大文字にする方式です。

キャメルケース単数形の例:MemberItem

 

補足:テーブルの命名規則

モデルに対するテーブル名の命名規則は、スネークケースの複数形となります。

スネークケースとは複数単語でテーブル名を構成する場合、各単語の間をアンダーバーにする方式です。

スネークケース複数形の例:member_items
 
 
おすすめ本


 

Model(モデル)に書くべき基本的な内容

まず、基本的なModelに書くべき内容のfiilableまたはguardedについて紹介します。

前提としてModelファイルをコマンドで作成したときは、デフォルトで下記のようになっています。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Member extends Model
{
    use HasFactory;
}

デフォルトの状態に必要な記述を加えていきます。

 

fillableまたはguarded

データベースにデータを登録または更新したい場合は、fillableまたはguardedを記載する必要があります。

fillableはデータ登録、更新を許可するカラムを指定します。

guardedはデータ登録、更新を許可しないカラムを指定します。指定したカラム以外は許可されます。

例をあげて解説していきます。

 

fillableの設定例

membersテーブルには「名前」「メールアドレス」「電話番号」「住所」のカラムがあり、そのカラムにデータを登録または更新ができるようにModelで定義します。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Member extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'mail',
        'tel',
        'address',
    ]
}

このように設定することで、指定したカラムの登録または更新を許可します。

 

guardedの設定例

membersテーブルには「名前」「メールアドレス」「電話番号」「住所」のカラムがあり、そのカラムにデータを登録または更新ができるようにModelで定義します。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Member extends Model
{
    use HasFactory;

    protected $guarded = [
        'id',
    ]
}

guardedにはidを指定しました。

idカラム以外の全てのカラムに対して、登録と更新を許可できます。

idは自動採番(AUTO_INCREMENT)を使用することが多く、idに対して登録または更新する処理をすることは基本的にはありません。

なのでguardedにidを指定する方法が良いのではないでしょうか。

 

fillableとguardedのどちらを使用すればよいか

結論、guardedを使用するべきだと思います。

fillableで指定すると、テーブルのカラム追加がされる度にfillableにカラムを定義する必要があります。

一方、guardedであればテーブルのカラムが増えてもguardedの改修をする必要がありません。

 

登録・更新メソッドについて

fillableまたはguardedのデータ登録または更新の許可が適用される代表的なメソッドは下記です。

create(登録処理をするメソッド)

update(更新処理をするメソッド)

fill + save (登録・更新処理をするメソッド)

ちなみに下記のメソッドはfiilableまたはguardedの定義内容に関係なく、処理を実行します。
insert (直でSQLを実行し、データを登録する処理)
直でSQLを実行するためModelの影響をうけません。
しかし、これはデメリットが発生します。
insertメソッドはデメリットがいくつかあるため、使用には注意が必要です。
こちらの内容は別の記事で紹介する予定です。

 

Model(モデル)に書くことが多い内容をピックアップ

必須ではありませんが、よくModelで使用されるものをピックアップしておきます。
これを頭に入れておくと、Modelでできる事がイメージできるでしょう。

・カラムの型の定義

・親子関係の定義(リレーション)

・データベースのカラム取得時の値変換(アクセサ)

・データベースのカラム登録時の値変換 (ミューテタ)

 

型定義

$castsでカラムに対しての型を定義することが可能です。

データベースのテーブル作成時にカラムの型定義ってされてるけど、モデルで定義する必要があるんですか?

モデルの型定義をしない場合、例えば$query->first()でデータを取得した際にintegerで定義していたものもstringになってしまいます。

モデルで型を定義しておけば、データ取得時に指定した型で取得することが可能です。

型の定義の仕方は下記です。

protected $casts = [
    'name' => 'string',
    'price' => 'integer',
    'flag' => 'boolean'
];

 

親子関係の定義(リレーション)

Modelでリレーションを定義することによってリレーション先にアクセスすることが簡単にできます。

メソッドによって定義できる内容が異なります。

hasOneメソッド

belongsToメソッド

hasManyメソッド

belongsToManyメソッド

 

hasOneメソッド

メソッドについて、親テーブルのusersテーブルと子テーブルのphonesテーブルを例にして解説します。

usersテーブル(親テーブル)とphonesテーブル(子テーブル)の関係は1対1です。

この場合の、親テーブルから見た子テーブルのリレーション定義はhasOneメソッドを使います。

 

Userモデル

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
     public function phone()
    {
        return $this->hasOne('App\Models\Phone');
    }
}

 

belongsToメソッド(1対1)

メソッドについて、親テーブルのusersテーブルと子テーブルのphonesテーブルを例にして解説します。

usersテーブル(親テーブル)とphonesテーブル(子テーブル)の関係は1対1です。

この場合の、子テーブルから見た親テーブルのリレーション定義はbelongsToメソッドを使います。

 

Phoneモデル

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
     public function phone()
    {
        return $this->belongsTo('App\Models\User');
    }
}

 

hasManyメソッド

メソッドについて、親テーブルのcompanysテーブルと子テーブルのemployeesテーブルを例にして解説します。

companysテーブル(親テーブル)とemployeesテーブル(子テーブル)の関係は1対多です。

この場合の、親テーブルから見た子テーブルのリレーション定義はhasManyメソッドを使います。

 

Companyモデル

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Company extends Model
{
     public function employee()
    {
        return $this->hasMany('App\Models\Company');
    }
}

 

belongsToメソッド(1対多)

メソッドについて、親テーブルのcompanysテーブルと子テーブルのemployeesテーブルを例にして解説します。

companysテーブル(親テーブル)とemployeesテーブル(子テーブル)の関係は1対多です。

この場合の、子テーブルから見た親テーブルのリレーション定義はbelongsToメソッドを使います。

belongsTo子テーブルから親テーブルのリレーションを定義する際に、1対1でも1対多でも使用されます。

 

Employeeモデル

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Employee extends Model
{
     public function company()
    {
        return $this->belongsTo('App\Models\Employee');
    }
}

 

belongsToManyメソッド

belongsToManyメソッドは複雑なので、別の記事で詳しく解説します。

 

データベースのカラム取得時の値変換(アクセサ)

アクセサとは、データベースからデータを取得する時に走る処理のことです。

データベースからデータを取得する時に、そのまま取得するのではなく変換処理をさせたい場合に便利です。

 

アクセサの使用例

例えば、データベースに氏名を「姓」と「名」の別カラムで保存させている状況で、「姓+名」でデータを取得したいとします。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $append = ['full_name'];

    public function getFullNameAttribute()
    {
        return $this->first_name . " " . $this->last_name;
    }
}

get○○Attributeでアクセサを定義します。

アクセサの命名規則キャメルケースで記載するルールになっています。

(キャメルケース例:getFullNameAttribute)

上記のコードではgetFullNameAttributeでLaravelがアクセサであることを判断し、full_name属性を作成します。

実際に姓+名でデータが取得できるか試します。

$user->first();
$user->full_name;

 

アクセサの定義をしたfull_nameで「姓名」を取得することができるようになります。

 

データベースのカラム登録時の値変換 (ミューテタ)

ミューテタとは、データベースにデータを保存する時に走る処理のことです。

データベースからデータを保存する時に、そのまま保存するのではなく変換処理をさせたい場合に便利です。

 

ミューテタの使用例

例えば、データベースに氏名の「名」を大文字変換して登録したいとします。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function setFirstNameAttribute($value)
    {
        $this->attributes['first_name'] = strtoupper($value);
    }
}

set○○Attributeでミューテタを定義します。

ミューテタの命名規則は先程と同様に、キャメルケースで記載するルールになっています。

(キャメルケース例:setNameAttribute)

strtoupperで$valueの値を大文字変換しています。

実際にデータを保存してみます。

$user = User::first();
$user->first_name = 'ken';
$user->save();

$user->first_nameを保存する時に、UserモデルのsetFirstNameAttributeの処理を通過して大文字変換されてデータが保存されます。

 

コメント