2017-02-20 68 views
0

Моего вопроса основан на Data Viewer with Laravel 5.3 and Vue.jsКак и почему этот код работает?

Этот чувак создает признак DataViewer и коды это похоже на следующее:

trait DataViewer 
{ 
    // $query should be a Query Builder 
    public function scopePaginateAndOrder($query) 
    { 
     // Validation ... 

     // Where, Pagination, Order etc ... 
     return $query->where('foo', 'like', 'bar'); 
    } 
} 

Теперь вы можете использовать эту особенность в любых красноречивых моделях, чтобы добавить функцию поиска.

class Customer extends Model 
{ 
    use DataViewer; 
} 

Все обычные вещи, ничего особенного ... но есть некоторые «магия» я did't увидеть в PHP еще.

В контроллере он делает что-то вроде

$model = App\Customer::paginateAndOrder(); 

Последний фрагмент кода имеет много аспектов я не могу понять.

  1. Почему я называю это нестатическим-методом в статическом-методе, как с помощью ::?
  2. Почему я могу опустить сфера действия от имени метода?
  3. Мне не нужно передавать объект Query Builder в качестве параметра. Итак, как черта «знает», на какой модели я хочу разбивать/упорядочивать

Спасибо за помощь!

+0

«Мне не нужно передавать объект Query Builder в качестве параметра', а' // $ query должен быть построителем запросов »- это плохая практика (should/can/...). Почему функция не выглядит так: 'public function scopePaginateAndOrder (QueryBuilder $ query = null)'? На '1.' он выдает примечание/предупреждение в php' Строгие стандарты: нестатический метод ', но вызов будет вызван. Что значит «2.»? – JustOnUnderMillions

+0

И кстати: как только вы поговорите о 'scopePaginateAndOrder', то о' paginateAndOrder', будет 2 diff. метод называется не то же самое. поэтому вы не можете опустить «область» при попытке вызвать «scopePaginateAndOrder()». В вашей логике происходит что-то другое. – JustOnUnderMillions

+0

Хорошо, но не тип, намекающий на параметр, действительно является плохой практикой, я просто сделал копию и вставку из вышеупомянутого связанного видео. И да, мне нужно использовать paginateAndOrder() INSTEAD of scopePaginateAndOrder(), иначе это вызовет исключение – Qobus

ответ

1

Laravel хорошо использует несколько магических методов PHP, в частности в этом случае __call() и __callStatic.

http://php.net/manual/en/language.oop5.overloading.php#object.callstatic

С callStatic, если статический метод вызывается, что либо не существует или недоступен, то вызов будет делегирован методу __callStatic() в этом классе (если таковой существует). То же самое верно __call() и методы экземпляра.

Если вы посмотрите в Illuminate\Database\Eloquent\Model вы найдете:

/** 
* 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'])) { 
     return call_user_func_array([$this, $method], $parameters); 
    } 

    $query = $this->newQuery(); 

    return call_user_func_array([$query, $method], $parameters); 
} 

/** 
* Handle dynamic static method calls into the method. 
* 
* @param string $method 
* @param array $parameters 
* @return mixed 
*/ 
public static function __callStatic($method, $parameters) 
{ 
    $instance = new static; 

    return call_user_func_array([$instance, $method], $parameters); 
} 

В приведенном выше, если __callStatic вызывается, то это создаст new экземпляр модели и попытаться вызвать метод этого экземпляра, так когда вы вызываете App\Customer::paginateAndOrder(), он затем попытается вызвать paginateAndOrder() в качестве метода экземпляра.

(не входит в increment и decrement) В __call() метод на модели будет попробовать и вызывать этот метод на Illuminate\Database\Eloquent\Builder. Builder тогда имеет собственный __call() метод, который в нем следующее:

if (method_exists($this->model, $scope = 'scope' . ucfirst($method))) { 
    return $this->callScope([$this->model, $scope], $parameters); 
} 

callScope затем просто назвать фактический scopePaginateAndOrder и передает Builder через.

Надеюсь, это поможет!

1

Это волшебство Laravel .. не php вообще.

Laravel использует то, что известно с magic functions

  1. Почему я называю это Нестатические-метод в статическом-метод, как с помощью ::?

Я только список два здесь __call() и __callStatic() эти функции вызывается при вызове несуществующих нестатические статические функций соответственно ..

Так Illuminate\Database\Eloquent\Model что супер-класса для все модели делают это, проверьте это link.

  1. Почему я могу опустить область действия из имени метода? '

Просто Laravel позволяет опускать префиксы имен функций, которые представляют собой то, что он делает. например. префикс scope в вашем случае .. И продолжает добавлять префиксы в определенном порядке, пока не найдет его. Прочтите code, если вам нужен более внимательный взгляд.

  1. Мне не нужно передавать объект Query Builder в качестве параметра.Так как же черта «знать», какую модель я хочу постраничной/заказать

Я считаю, что это связано с Laravel IoC контейнера и инъекции dependcy ..

Примечание: Q3 необходимо больше исследований для обязательно, когда &, как производится инъекция.