🐞

Laravel 9.35 Model::preventAccessingMissingAttributes を試しつつ、注意点にも触れてみる

2022/10/12に公開

前書き

Laravel 9.35 の新機能の1つ、Model::preventAccessingMissingAttributes() を試してみましたので、その様子とついでに注意点についても触れてみたいと思います。

[9.x] Opt-in Model::preventAccessingMissingAttributes() option #44283

本題

少し長いメソッド名ですが、この機能、要はバグを減らすための機能です。
今までの Laravel では、Eloquent モデルで存在しないプロパティにアクセスしても、特にエラーは出ずに、null が返されてスルーされていましたが、それを防ぐ(エラーとする)事ができる機能です。

この機能をオンにするには、例えば、AppServiceProvider で以下のように記述します。

AppServiceProvider
<?php

use Illuminate\Database\Eloquent\Model;

class AppServiceProvider extends ServiceProvider
{
    // 略

    public function boot()
    {
        // 本番環境以外で有効にする
        Model::preventAccessingMissingAttributes(! $this->app->isProduction());
    }
}

これでオンになりました。

で、エラー(例外)が出るのは、「(1) 存在しないプロパティにアクセスしようとして(accessors / casts / relations 等は除く)」且つ「(2) そのモデルがDBに存在する時」のみです。言い換えれば、DBに保存していないモデルは、この機能の対象ではありません。例えば下記みたいなケースです。(DBにはデータがある前提)

(2024年1月追記:Ver.10.40 辺りからは、casts にも改良が加わっています)

// ケース1
$user = User::first();
$user->emailll;  // email の綴りミス

// ケース2
$user = User::select('id', 'name')->first();
$user->email;  // select() に email を追加忘れ

今までですと、単に null となってスルーされていましたが、この機能をオンにしていると、、、

Illuminate \ Database \ Eloquent \ MissingAttributeException

The attribute [emailll] either does not exist or was not retrieved for model [App\Models\User].

みたいなエラーとなって、処理が終了します。これで不要なバグの心配をしなくて済みます。

Model::shouldBeStrict()

そして、このプルリクがマージされる直前に Taylor さんによって、shouldBeStrict() というメソッドが追加されました。

これは何かと言うと、既に以前から存在する機能の preventLazyLoading() と preventSilentlyDiscardingAttributes() と今回の機能をまとめて有効に出来るメソッドです。

ですので、AppServiceProvider で、

AppServiceProvider
use Illuminate\Database\Eloquent\Model;

    public function boot()
    {
        Model::shouldBeStrict(! $this->app->isProduction());
    }

とやっておけば、開発環境でまとめて3つ設定した事になります。楽でいいですね。

注意点⚡⚡⚡

例によって、注意点があります。今回の機能を有効にする際は、

// 正解
Model::preventAccessingMissingAttributes();

// 不正解(prevents と最後に s がある。こちらは設定状況を返す)
Model::preventsAccessingMissingAttributes();

どちらもメソッドは存在しますので、この罠に掛からないようご注意下さい。掛かってしまうと、設定したつもりが、実は設定されていないという事になってしまいます。
(以前、同じような事を書いた記憶がありますが…)

で、最初にこの罠に掛かってしまった方は、、、、、そう、あの Taylor さんですね。😅

先程の shouldBeStrict() メソッド内のこの機能を有効にする箇所で、上記をミスっていて、そのままマージされていました。

で、犬も歩けば棒に当たる理論で、たまたまプルリクなどを見ていた私が気づいたので、それの修正用のプルリクを送り、マージされました。
[9.x] Fix method name in shouldBeStrict method #44520

修正箇所、たった1文字。修正箇所の少なさでは、かなりの上位です。まぁ、自分で言うのも何ですが、私のスキルレベルに見事マッチしたプルリクですね。(^3^)ぷっ

Taylor さんも間違えてしまうという事は、まぁ、皆間違えてしまいますよ…。
という事で、バグを減らす機能のオンでバグらないようご注意下さい。

と、、、これで終わっていれば良かったのですが、先程公開されたと思われる Laravel News でもミスってる…🤣

Laravel 9.35 Released!

ミス画像

いや~、どうした事か。Laravel News にプルリク送る?そんなの無いでしょ…💦

雑感

今日はこの辺で失礼します😪

Discussion