わかりました...これはあなたの脳を少し歪めるかもしれませんが、私に固執してください. 定義されている実際のメソッドは _where() です。では、Post::where と $post->where の両方が最終的に _where() メソッドを呼び出すのはなぜでしょうか? 答えは「魔法」です。:D
PHP には、非常に動的な動作を可能にする「マジック メソッド」と呼ばれるものがあります。この場合、Laravel は __callStatic() および __call() を使用して、未定義のメソッドへの呼び出しを処理しています。これにより、同じメソッドを静的および非静的に呼び出すことができました。
public static function __callStatic($method, $parameters)
{
// Create a new instance of the called class, in this case it is Post
$model = get_called_class();
// Call the requested method on the newly created object
return call_user_func_array(array(new $model, $method), $parameters);
}
したがって、基本的に Post::where() は $post = new Post; の省略形です。$post->where()
ここからリクエストは、下線付きのメソッド名の配列がある __call() に行きます。要求されたメソッドが下線付きの名前のリストにある場合、$this->_method() が呼び出されて返されます。
しかし、これはまだすべてではありません。「where_in」が Query オブジェクトを返すという点で Drew は正しいです。よく知っている ORM チェーン メソッドのほとんどは、実際には ORM Query オブジェクトの一部です。これがプロセス全体です。
- Post::where( ... )
- Post::__callStatic( 'where', ... )
- $post->__call( '場所', ... )
- $query->_call( 'where', ... )
- $query->_where( ... )
拡張するクラスは、モデルで使用されるクエリです。__call() で定義されている下線付きのメソッドのリストに別のメソッド名を追加する方法はありません。新しいメソッドがその動作を行えるようにするには、__call() 全体をクエリ定義にコピーする必要があります。
私のプロジェクトでは、Eloquent (Laravel モデルのエイリアス) を拡張バージョンに向けることでこれを達成し、すべてのモデルが拡張 Query メソッドを使用できるようにしました。
// application/libraries/mylib/query.php
namespace MyLib;
class Model extends \Laravel\Model {
// Tell \MyLib\Model to use \MyLib\Query instead of Laravels Query
protected function query()
{
return new \MyLib\Query($this);
}
}
// application/libraries/mylib/query.php
namespace MyLib;
class Query extends \Laravel\Database\Eloquent\Query {
function _my_method() { ... }
function __call() { ... }
}
// application/config/application.php
'aliases' => array(
...
'Eloquent' => 'MyLib\\Model',
...
)
http://php.net/manual/en/language.oop5.magic.php
https://github.com/laravel/laravel/blob/master/laravel/database/eloquent/model.php#L734
https:// github.com/laravel/laravel/blob/master/laravel/database/eloquent/query.php#L274