2017-02-20 82 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

'我不必将查询生成器对象作为参数传递,'//查询应该是查询生成器'是不好的做法(应该/可以/ ...)。为什么函数不是这样的:'public function scopePaginateAndOrder(QueryBuilder $ query = null)'?在'1.'上,它会在php'严格标准:非静态方法'中抛出一个注释/警告,但是这个方法将被调用。用'2'来表示什么意思? – JustOnUnderMillions

+0

顺便说一句:一旦你谈到'scopePaginateAndOrder'那么关于'paginateAndOrder',就会有2个diff。方法调用,不一样。所以当你尝试调用scopePaginateAndOrder()时,你不能忽略'范围'。你的逻辑中出现其他问题。 – JustOnUnderMillions

+0

好吧,不是键入提示参数确实是一个不好的做法,我只是从上面的链接视频做了一个复制和粘贴。是的,我必须使用paginateAndOrder()INSTEAD 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()作为实例方法。

(不包括incrementdecrement)模型上的__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

  • 我不必须通过查询生成器对象作为参数。那么,如何特质“知道”上的模型,我想分页/订单
  • 我相信这是由于Laravel IoC容器和dependcy注射..

    注:Q3需要更多的研究来请务必当&如何注射。