九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、Laravelで開発をしているとき、とても重宝する機能の一つに、「データのキャスト(型変換)」があります。
キャストというのは、例えば文字列で登録したデータを数字に変換する機能で、通常のPHPだと、
$text = (string) 123;
とすることで型変換できるわけですけど、なんとLaravel
の場合はモデルの$casts
に指定するだけで、
- 保存する時
- 取得する時
の両方で、自動的に型変換をしてくれてとても便利です。(そして、変数の型だけじゃなく配列やコレクションに変換もしれくれます。)
例えばこんなカンジです。
class Item extends Model { protected $casts = [ 'activated' => 'boolean' ]; }
とうことで、今回はこの「キャスト」の実例をまとめてみました。
開発環境: Laravel 5.4、Laravel 7.x
【追記:2020.03.10】この記事は、公開当時Laravel 5.4
向けに作成されていたものに加筆修正したものです。
目次
Integer
数字へ変換するキャストです。
もしデータが文字列でもこのキャストを使うことで型を数字にすることができます。
protected $casts = [ 'field_name' => 'integer' ];
例えば、”12345″という文字列がキャストされると、数字の「12345」に変換されます。
var_dump($item->field_name); // int(12345)
ちなみに、もし文字列で “1234.555”などのように小数点がついている場合は、小数点以下が削除されて「1234」となります。(四捨五入ではない)
また、「150個」「150円50銭」という文字列の場合は、最初に出てくる数字「150」が取得できます。
float(real, double)
データを小数点つきの数字に変換するキャスト。(real
とdouble
は同じものなので、float
で統一します)
protected $casts = [ 'field_name' => 'float' // もしくは、real か double ];
もし”123.456″という文字列がfloatキャストされると、「123.456」という小数点付きの数字になります。
var_dump($item->field_name); // float(123.456)
integerキャストと同じく、”123.456回”や”123.456円50銭”の場合は、「123.456」という小数点付きの数字になります。
String
データを文字列化するキャストです。
protected $casts = [ 'field_name' => 'string' ];
例えば、「12345」という数字がキャストされると”12345″という文字列に変換されます。
var_dump($item->field_name); // string(5) "12345"
ちなみに、float型の場合も同様に文字列に変換されます。
var_dump($item->field_name); // string(7) "12345.6"
boolean
データをtrueもしくは、falseに変換するキャストです。
protected $casts = [ 'field_name' => 'boolean' ];
例えば、データが「1」という数字の場合は以下のようにtrueになり、「0」の場合はfalseになります。
var_dump($item->field_name); // bool(true) もしくは bool(false)
ちなみに、trueになるパターン、falseになるパターンは以下のとおりです。
- true ・・・ 1, 2, -1
- false ・・・ 0, 文字列の空白
※マイナス1は直感的にfalseになりそうですけど、実際にはtrueになってしまうので注意が必要ですね。
object
PHPの「stdClass」に変換されるキャストです。
protected $casts = [ 'colors' => 'object' ];
例えば、以下のように連想配列を保存すると、json化されてデータベースに格納されます。(連想配列、多次元配列でもOK)
\App\Item::create([ 'colors' => [ 'red' => '赤', 'blue' => '青', 'yellow' => '黄色' ] ]);
↓↓↓DB内
{"red":"\u8d64","blue":"\u9752","yellow":"\u9ec4\u8272"}
そして、データ取得した場合は、以下のようにstdClassとして利用できます。
var_dump($item->colors->red); // string(3) "赤" var_dump($item->colors->blue); // string(3) "青" var_dump($item->colors->yellow); // string(6) "黄色"
ちなみに、stdClassはforeach()ループで使うこともできます。
foreach ($item->colors as $key => $value) { echo $key .': '. $value ."\n"; } /*** 出力 red: 赤 blue: 青 yellow: 黄色 ***/
array
データを配列化してくれるキャストです。
protected $casts = [ 'colors' => 'array' ];
配列を保存すると、データがjson化されます。(連想配列、多次元配列でもOK)
\App\Item::create([ 'colors' => [ '赤', '青', '黄色' ] ]);
↓↓↓DB内
["\u8d64","\u9752","\u9ec4\u8272"]
取得したところ。
var_dump($item->colors); /*** 出力 array(3) { [0]=> string(3) "赤" [1]=> string(3) "青" [2]=> string(6) "黄色" } ***/
collection
Laravelの「コレクション」に変換してくれるキャストです。
これも「array」や「object」などと同じく保存するとjson化されます。
protected $casts = [ 'colors' => 'collection' ];
データ取得するとこうなります。
var_dump($item->colors); /*** 出力 object(Illuminate\Support\Collection)#699 (1) { ["items":protected]=> array(3) { ["red"]=> string(3) "赤" ["blue"]=> string(3) "青" ["yellow"]=> string(6) "黄色" } } ***/
date, datetime
Carbonインスタンスに変換してくれるキャストです。
protected $casts = [ 'start_date' => 'date', 'start_datetime' => 'datetime' ];
var_dump($item->start_date); /*** 出力 object(Illuminate\Support\Carbon)#700 (3) { ["date"]=> string(26) "2018-05-15 00:00:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(10) "Asia/Tokyo" } ***/
dateとdatetimeの違いは、dateの場合、時間/分/秒が全てゼロになることです。これは、データが「2018-05-15 01:15:30」という風に時分秒が指定されていても同じです。
echo $music->start_date->hour; // 0 echo $music->start_date->minute; // 0 echo $music->start_date->second; // 0
ちなみに、データが空白の場合は「Data missing」というエラーが発生します。
なお、以下のように日付のフォーマットを指定することができます。
protected $casts = [ 'start_date' => 'datetime:Y年m月d日' ];
詳しくは、過去記事「Laravel5.6の気になる3つの新機能」の「2.モデル内の日付・自動変換」を参照してください。
timestamp
データをUNIX時間に変換してくれるキャストです。つまりint型になります。
protected $casts = [ 'created_at' => 'timestamp' ];
var_dump($item->created_at); // int(1526314530)
カスタムキャスト機能
Laravel 7.x
からは、独自キャストを作ることができる「カスタムキャスト機能」が追加になっています。詳しくは以下のURLをご覧ください。
Laravel 7.xの新しいキャスト(データ変換)機能!実例
クエリー用の時間キャスト
【注意】この機能は、Laravel 7.x
以降で有効です。
例えば、users
とposts
が1:多(hasMany)の関係にあるとして、「認証されたpostデータの最新の日付を取得する」場合を考えてみましょう。
コードとしては以下のようになります。
$users = \App\User::select([ 'users.id', 'verified_at' => \App\Post::selectRaw('MAX(verified_at)') ->whereColumn('user_id', 'users.id') ])->get();
ただ、この場合だとverified_at
は文字列なので、日付オブジェクトとして使う場合はnew Carbon()
で変換する必要があり、めんどうです。
そんな場合に重宝するのが、withCasts()
です。
以下のように使うことで、元々は文字列だったverified_at
を日付にキャストすることができます。
$users = \App\User::select([ 'users.id', 'verified_at' => \App\Post::selectRaw('MAX(verified_at)') ->whereColumn('user_id', 'users.id') ])->withCasts([ 'verified_at' => 'date' // 日付に変換 ])->get();
おわりに
ということで、今回はキャストをまとめてみました。
みなさんのお役に立てたら嬉しいです!
ではでは〜。