Closed6
備忘録 Modelのfindメソッドが呼ばれる仕組み
findはEloquent\Builderのメソッド
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
が得られる
これで、EloquentBuilder
のfind
メソッドとして実行できる
このスクラップは2024/02/25にクローズされました