создание цепного метода в ларавеле

Я пытаюсь создать свой собственный цепной метод в 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(); 

если я правильно понял, то мой метод не имеет права на цепочку после другого метода? Поэтому, я думаю, мой вопрос заключается в том, как я могу создать цепочечный метод в моей модели?

PS Я заглянул в класс построителя запросов laravel, где я видел, что методы chainable возвращают экземпляр этого объекта, но я не смог найти способ вернуть объект, отличный от того, как я это сделал в приведенном выше коде. Любое предложение или совет высоко ценятся. Заранее спасибо.

С вашего вопроса Laravel предлагает новый способ сделать это, называемый «областью запросов». Вы можете найти документ здесь .

Вам просто нужно написать функцию с scope префикса, и вы сможете связать этот метод, как и другие построители запросов:

 class Post extends Eloquent { public function scopeWhereCategories($query, $categories) { return $query->whereIn('categories_id', $categories, 'AND'); } } $posts = Post::whereCategories(array(1, 2, 3))->get(); $posts = Post::orderBy('date')->whereCategories(array(1, 2, 3))->take(5)->get(); 

Хорошо … Это может немного испортить ваш мозг, но со мной. Фактический метод определяется как _where (). Итак, как работают как Post :: where, так и $ post->, где в конечном итоге вызывается метод _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-> где ()

Отсюда запрос отправляется в __call (), в котором имеется массив имен подчёркнутых методов. Если запрошенный метод находится в списке подчеркнутых имен, тогда вызывается и возвращается $ this -> _ method ().

Но это еще не вся история. Дрю прав в том, что 'where_in' возвращает объект Query. Большинство методов цепочки ORM, с которыми вы знакомы, на самом деле являются частью объекта ORM Query. Вот весь процесс.

  • Сообщение :: где (…)
  • Post :: __ callStatic ('where', …)
  • $ post -> __ call ('where', …)
  • $ query -> _ call ('where', …)
  • $ query -> _ где (…)

Класс, который вы хотите расширить, – это запрос, который используется моделью. Невозможно добавить другое имя метода в список подчёркнутых методов, определенных в __call (). Вам нужно будет полностью скопировать __call () в ваше определение Query, чтобы ваш новый метод имел такое поведение.

Я выполнил это в своих проектах, указав 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, она возвращает объект типа Query.

Поскольку вы просто создали свою пользовательскую функцию, я бы просто избегал функции

 $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. И тогда вы сможете объединить свои собственные методы.