Laravelでboolean型にしたはずのデータがint型で返ってくる
IT技術
Laravelのマイグレーションファイルでは確かにboolean型を指定してるのに実際にDBからデータを持ってくるとint型になっているということがあると思います。
私もそこで引っかかったのでその解決策について書いていきたいと思います。
環境
今回の開発環境は以下の通りです。
- PHP 8.1.2
- Laravel 9.37.0
- MySQL 5.7.36
DBにはint型で保存される
Laravelのマイグレーションファイルではカラムの型指定でboolean型が指定できます。
1public function up()
2 {
3 Schema::create('users', function (Blueprint $table) {
4 // 省略
5 $table->boolean('is_admin')->default(0);
6 });
余談ですがboolean型のカラム名は命名規則で「is_xxx」とするようです。
上記のようにカラムの型をbooleanに指定したとしても実際にDBにはint型で保存されています。
なのでDBからデータを引っ張ってきてもboolean型ではなくint型で返ってきます。
ですが実際に使うと時はboolean型で使いたい事があります。
そんな時はモデルでキャストする事で解決できます。
モデルでキャストしてboolean型にする
Laravel内のモデルクラスでキャストすることでカラムの値をboolean型として取ってくることができます。
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Model;
6
7class User extends Model
8{
9 // 省略
10
11 /*
12 * @var array
13 */
14 protected $casts = [
15 'is_admin' => 'boolean',
16 ];
17}
上記のようなコードで該当のカラムをキャストしてboolean型にします。
このように定義していればDBにはint型で保存されている値もboolean型で扱えるようになります。
1$user = App\Models\User::find(1);
2
3$isAdmin = $user->is_admin;
上記のようにして取得すればis_adminの値をboolean型で扱えます。
中間テーブルの値をキャストしたい時
中間テーブルを使用する場合はカスタム中間テーブルモデルを使用します。
中間テーブルのカラムの値にboolean型を指定している場合は必ずカスタム中間テーブルモデルを定義してそのモデル内でキャストします。
その上でモデルのリレーションを定義して中間テーブルのカラムを取ってくればboolean型で扱えます。
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Relations\Pivot;
6
7class RoleUser extends Pivot
8{
9 /*
10 * @var array
11 */
12 protected $casts = [
13 'is_admin' => 'boolean',
14 ];
15}
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Model;
6
7class User extends Model
8{
9 public function roles()
10 {
11 return $this->belongsToMany(Role::class)->using(RoleUser::class)->withPivot('is_admin');
12 }
13}
1<?php
2
3namespace App\Models;
4
5use Illuminate\Database\Eloquent\Model;
6
7class Role extends Model
8{
9 public function users()
10 {
11 return $this->belongsToMany(User::class)->using(RoleUser::class)->withPivot('is_admin');
12 }
13}
実は中間テーブルを用いた各モデルには自動的にpivotという属性が割り当てられています。
デフォルトではモデルキーのみ(ここではuser_id,role_id)しか割り当てられていないので
「withPivot('is_admin')」を書くことでpivot属性にis_adminも割り当ててあげます。
そして値を取ってくるには以下のように書きます。
1use App\Models\User;
2
3$user = User::find(1);
4
5foreach ($user->roles as $role) {
6 echo $role->pivot->is_admin;
7}
このようリレーションからpivot属性を経由してis_admin の値を取ってくることでbooleanとして扱えます。
必ずEloquentで取ってこないといけない
キャストした値を取ってくる上での注意点があります。
それは必ずEloquentでカラムの値を取ってこなければならないということです。
キャストの定義はモデルクラスで行っているので、モデルクラスを経由して値を取ってこなければキャストは適用できません。
今回の例で言うならば、EloquentでUserモデルから値を取ってこないとis_adminの値をboolean型で扱えません。
例えば以下のようにクエリビルダで直接DBから値を取ってきたとしましょう。
1$user = DB::table('users')->find(1);
2
3$isAdmin = $user->is_admin;
このような書き方をしている場合はint型で返ってきしまうので気をつけましょう。
まとめ
今回はboolean型を例にキャストについて書いてみました。
キャストの用途としては、他にもdatetime型の表記方法を操作する時などにも使えます。
DBに入れた値と実際に期待している値が違う時はぜひ使ってみてください。
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ