Мой вопрос основан на Просмотр данных с помощью Laravel 5.3 и 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');
}
}
Теперь вы можете использовать эту черту в любой модели Eloquent для добавления функций поиска.
class Customer extends Model
{
use DataViewer;
}
Все обычные вещи, ничего особенного …
но есть некоторая «магия», которую я еще не видел в PHP.
В контроллере он делает что-то вроде
$model = App\Customer::paginateAndOrder();
Последний фрагмент кода имеет много аспектов, которые я не могу понять.
Спасибо за вашу помощь, ребята!
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
через.
Надеюсь это поможет!
Это магия Laravel .. вообще не php.
Laravel использует то, что известно с магические функции
- Почему я могу вызывать этот нестатический метод статическим методом, используя ::?
Я перечислю только два здесь __call()
а также __callStatic()
эти функции вызываются, когда вы вызываете несуществующие нестатические статические функции соответственно ..
Так в Illuminate\Database\Eloquent\Model
который является суперклассом для всех моделей, проверьте это ссылка на сайт.
- Почему я могу опустить область из имени метода?
Просто Laravel позволяет вам пропустить префиксы имен функций, которые представляют то, что он делает. например. scope
префикс в вашем случае .. И продолжает добавлять префиксы в определенном порядке, пока не найдет его.
Прочитайте код если вы хотите поближе.
- Мне не нужно передавать объект Query Builder в качестве параметра. Так как же черта «узнает», какую модель я хочу разбить на страницы / заказать?
Я считаю, что это связано с контейнером Laravel IoC и инъекцией зависимости.
Примечание: Q3 нуждается в дополнительном исследовании, чтобы быть уверенным, когда & как делается инъекция