php-laravelでチェーン可能なメソッドを作成する
laravelの雄弁な方法で独自のチェーン可能なメソッドを作成しようとしていますが、何かが足りず、何がわからないのです。これは少しおかしなことに聞こえるかもしれませんが、私が何を言おうとしているのかをよりよく理解するために、以下の私の関数を見てください。
class Post extends Eloquent{
public static function custom_wh($data){
return static::where_in('categories_id', $data, 'AND');
}
}
//this works fine
$posts = Post::custom_wh(array(1, 2, 3))->get();
//but this says custom_wh is not defined in the query class
$posts = Post::where_in('tags', array(2, 3, 4), 'AND')->custom_wh(array(1, 2, 3))->get();
正しく理解している場合、私のメソッドは別のメソッドの後にチェーンする資格がありませんか?ですから、私の質問は、モデルでチェーン可能なメソッドを作成するにはどうすればよいかということだと思います。
P.S laravelのクエリビルダークラスを調べたところ、チェーン可能なメソッドがそのオブジェクトのインスタンスを返すことがわかりましたが、コードで行った方法以外にオブジェクトを返す方法が見つかりませんでしたその上。どんな種類の提案やアドバイスも大歓迎です。よろしくお願いします。
答え :
解決策:
Laravelで「queryscopes」を使用してこれを行うことができます。ドキュメントはここにあります。
プレフィックスscope
を付けて関数を作成するだけで、他のクエリビルダーのメソッドと同じようにこのメソッドをチェーンできます:
class Post extends Eloquent {
パブリック関数scopeWhereCategories($ query、$ category)
{{
$ query-> whereIn('categories_id'、$ category、'AND');を返します。
}
}
$ posts = Post :: whereCategories([1、2、3])-> get();
$ posts = Post :: orderBy('date')-> whereCategories([1、2、3])-> take(5)-> get();
答え :
解決策:
OK ...これはあなたの脳を少し歪めるかもしれませんが、私に固執します。定義されている実際のメソッドは_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 =newPostの省略形です。 $ post-> where()
ここから、リクエストは__call()に送られ、そこに下線付きのメソッド名の配列があります。要求されたメソッドが下線付きの名前のリストにある場合、$ this-> _ method()が呼び出されて返されます。
しかし、これはまだすべてではありません。 Drewは、「where_in」がQueryオブジェクトを返すという点で正しいです。使い慣れたORMチェーンメソッドのほとんどは、実際にはORMQueryオブジェクトの一部です。これがプロセス全体です。
- Post :: where(...)
- Post :: __ callStatic('where'、...)
- $ post-> __ call('where'、...)
- $ query-> _ call('where'、...)
- $ query-> _ where(...)
拡張するクラスは、Modelで使用されるクエリです。 __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
答え :
解決策:
私が正確かどうかはわかりませんが、これが私がすぐに思いついたものです...
Post :: where_in()は、クエリタイプのオブジェクトを返しているEloquentモデルを返していません。
カスタム関数を簡単に記述したので、関数は避けたいと思います
$posts = Post::where_in('tags', array(2, 3, 4))->where_in('categories_ids', array(1,2,3))->get();
頭のてっぺんから
次のようなものを試すことができます
class Post extends Eloquent {
public static function custom_wh($data=array()) {
return static::where_in('categories_id', $data);
// return type of query not eloquent
}
}
$posts = Post::custom_wh(array(1,2,3))->where_in('tags', array(2, 3, 4))->get();
クエリクラスを変更したい場合を除く
答え :
解決策:
「静的」の代わりに「自己」を使用してみましたか?私の知る限り、selfと属性/メソッドを使用し、サブクラスを使用していて、参照しているメソッドがメインクラスの属性/メソッドをオーバーライドしない場合、メソッド'where_inが返されます。 'Queryクラスの。そして、カスタムメソッドをチェーンできるようになります。
答え :
解決策:
実際には、雄弁なビルダーを簡単に拡張して実行するだけです:
$posts = Post::custom_wh(array(1, 2, 3))->get();
ここに私の答えがあります:Laravelカスタムモデルメソッド
また、スコープを使用しないでください。ただし、現在何をしているのかを正確に把握している場合を除きます。これも私の回答で明らかになっています。
同様の質問
私たちのウェブサイトで同様の質問で答えを見つけてください。