Closed6

備忘録 Modelのfindメソッドが呼ばれる仕組み

あかつかあかつか

Eloquent\Modelでは定義されていないので、__callで呼ばれる

vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
    /**
     * 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', 'incrementQuietly', 'decrementQuietly'])) {
            return $this->$method(...$parameters);
        }

        if ($resolver = $this->relationResolver(static::class, $method)) {
            return $resolver($this);
        }

        if (Str::startsWith($method, 'through') &&
            method_exists($this, $relationMethod = Str::of($method)->after('through')->lcfirst()->toString())) {
            return $this->through($relationMethod);
        }

        return $this->forwardCallTo($this->newQuery(), $method, $parameters);
    }
あかつかあかつか

ちなみに、スタティックで呼ばれても、普通のメソッド呼び出しに変わるみたい

User::find()は、(new User())->find()みたいな感じか(ちょっと自信ない)

vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
    /**
     * Handle dynamic static method calls into the model.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public static function __callStatic($method, $parameters)
    {
        return (new static)->$method(...$parameters);
    }
あかつかあかつか

findの話に戻って、

return $this->forwardCallTo($this->newQuery(), $method, $parameters);

に着目する

あかつかあかつか

トレイトのForwardsCalls

「オブジェクトとメソッドとパラメータ渡して、渡したオブジェクトのメソッドとして呼び出して、結果を返させる」ということをやっている

vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php
    /**
     * Forward a method call to the given object.
     *
     * @param  mixed  $object
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    protected function forwardCallTo($object, $method, $parameters)
    {
        try {
            return $object->{$method}(...$parameters);
        } catch (Error|BadMethodCallException $e) {
            $pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';

            if (! preg_match($pattern, $e->getMessage(), $matches)) {
                throw $e;
            }

            if ($matches['class'] != get_class($object) ||
                $matches['method'] != $method) {
                throw $e;
            }

            static::throwBadMethodCallException($method);
        }
    }
あかつかあかつか

$this->newQuery()EloquentBuilderが得られる

これで、EloquentBuilderfindメソッドとして実行できる

このスクラップは2024/02/25にクローズされました