エンジニアのひよこ_level10

毎日更新してた人。たまに記事書きます。

【Laravel】Modelクラスでクエリビルダが動く理由【409日目】

モデルでクエリビルダ?

モデルのクラスって、テーブルのレコードをオブジェクトにしたようなイメージでした。

でも、以下のようなコードを見ることがあると思います。

User::select('id')->first();

あれ?selectってクエリビルダだよな・・・

このUserってなんだ?クエリビルダ?モデルのクラス???

元コードを読んで見る

Modelクラス

    /**
     * Handle dynamic method calls into the model.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        if (in_array($method, ['increment', 'decrement'])) {
            return call_user_func_array([$this, $method], $parameters);
        }

        $query = $this->newQuery();

        return call_user_func_array([$query, $method], $parameters);
    }

    /**
     * Handle dynamic static method calls into the method.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public static function __callStatic($method, $parameters)
    {
        $instance = new static;

        return call_user_func_array([$instance, $method], $parameters);
    }

なにしてるの?

__callStatic

__callStaticはマジックメソッド。

静的呼び出しをされたときに使われます。

User::select('id')

このとき、 new staticでモデルのインスタンスを作成。そして call_user_func_arrayで モデルクラスのインスタンスが、 selectの関数を 'id'のパラメーターを引き継いで実行。

__call

__callStatic()によって、静的呼び出しだったものが、モデルクラスのインスタンスから呼び出されることになります。

次は、 __callです。静的呼び出しじゃなくなったので。

そこでは、メソッド名が ['increment', 'decrement']のどちらかか確認して、合っていれば、そのモデルクラスのメソッドを呼び出します。

なければここ! newQueryでクエリビルダ用にインスタンスを作って、そのインスタンスselectの関数を呼び出します!

Laravelの元コードを読むのは面白いよ!

ってことで、案外簡単に追うことができました。

Laravelの元コードは、こんな書き方あるのか!と勉強になることがたくさんあるので、是非読んでみてください!

このデザインパターン使ってるのか・・・!ってなることたくさんあります。おすすめです。

参考

PHP: in_array - Manual

PHP: call_user_func_array - Manual