2013-02-25 4 views
3

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

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

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

ответ

8

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

Вы просто должны написать функцию с префиксом 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(); 
+0

Любите эту функцию и уже ее используете: D Я знаю, что этого не было, когда я разместил свой вопрос, но я выбираю это как правильный ответ для других гуглеров, подобных мне. Благодарю. –

0

не уверен, что если я буду точен, но это то, что я придумал быстрый ...

Post :: where_in() не возвращает красноречивым модель она возвращается объект типа запроса.

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

$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(); 

если не вам хотел изменить класс запроса

+0

хорошо, это то, что я сделал, и он работает, но проблема в том, функция custom_wh не связана с цепочкой, поэтому предположим, что у меня есть огромный запрос, который должен выполнять несколько соединений, где клаузулы, поэтому я хочу обернуть их отдельными функциями и связать их по мере необходимости, а затем появится проблема. Еще одна причина, по которой я пытаюсь включить их в функцию, - это то, что ORM не должна быть моей моделью? и я также пытаюсь сохранить свой код «СУХОЙ». –

0

Вы пытались использовать 'se lf 'вместо' static '? Насколько я знаю, если вы используете self и атрибут/метод, а ваш подкласс и метод, на который вы ссылаетесь, не переопределяют атрибут/метод основного класса, он вернет в этом случае метод 'where_in 'класса Query. И тогда вы сможете объединить свои собственные методы.

11

ОК ... Это может немного испортить ваш мозг, но со мной. Фактический метод определяется как _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-> where()

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

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

  • Post :: где (...)
  • Post :: __ callStatic ('где', ...)
  • $ пост -> __ вызова ('где', ...)
  • $ запрос -> _ вызов ('где', ...)
  • $ запрос -> _ где (...)

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

Я достиг этого в своих проектах, указывая на Яркий (псевдоним модели Laravel) на мою расширенную версию, позволяя всем моим моделям использовать расширенные методы запроса.

// 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

+0

, что объясняет многое. Честно говоря, я не много разбирался в OO в php, и я начал использовать фреймворки, потому что я думал, что узнаю OO, когда я пойду так, да, это довольно много, чтобы справиться, но Lemme выстрелил в него, используя вашу технику , Я буду держать вас в курсе, если у меня возникнут дополнительные вопросы. Большое спасибо за помощь. –

Смежные вопросы