新聞中心
安裝了laravel-debugbar后打開一個(gè)列表頁(yè)面,發(fā)現(xiàn)頁(yè)面輸出有兩個(gè) select count(*) 語(yǔ)句,這是一個(gè)嚴(yán)重的設(shè)計(jì)缺陷呀。

創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于做網(wǎng)站、成都網(wǎng)站建設(shè)、祁縣網(wǎng)絡(luò)推廣、小程序開發(fā)、祁縣網(wǎng)絡(luò)營(yíng)銷、祁縣企業(yè)策劃、祁縣品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供祁縣建站搭建服務(wù),24小時(shí)服務(wù)熱線:028-86922220,官方網(wǎng)址:www.cdcxhl.com
查看代碼
$users = User::where('votes', '>', 100)->paginate(15);
$count = User::where('votes', '>', 100)->count();之前就感覺(jué)paginate分頁(yè)應(yīng)該是使用了count,但是不知道怎么取總量數(shù)據(jù)所以又寫了一個(gè)count()。
var_dump($users);
object(Illuminate\Pagination\LengthAwarePaginator)[306] protected 'total' => int 4289 protected 'lastPage' => int 143 protected 'items' => object(Illuminate\Database\Eloquent\Collection)[307] protected 'items' => array (size=30) 0 => ....
返回?cái)?shù)據(jù)里面 的確有 protected 'total',但是protected不能訪問(wèn)呀!
仔細(xì)看了一下文檔,$results->total(),原來(lái)取total需要的是方法,而不是屬性。
弄明白total的獲取以后,對(duì)paginate這個(gè)分頁(yè)方法產(chǎn)生了興趣。于是看了一下源碼。
paginate這個(gè)方法最后使用了
Illuminate\Pagination\LengthAwarePaginator
這個(gè)類是怎么調(diào)用的呢?
無(wú)論是User::where('votes', '>', 100)->paginate(15)還是User::paginate(15),
User繼承著Illuminate\Database\Eloquent\Model這個(gè)ORM類,但是在Model并沒(méi)有where和paginate這些方法或靜態(tài)方法,這是laravl使用的一種代碼設(shè)計(jì)模式,
/**
* 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是php類的魔術(shù)方法
http://php.net/manual/zh/language.oop5.overloading.php#object.callstatic
public static mixed __callStatic ( string $name , array $arguments )
在靜態(tài)上下文中調(diào)用一個(gè)不可訪問(wèn)方法時(shí),__callStatic() 會(huì)被調(diào)用。
$name 參數(shù)是要調(diào)用的方法名稱。$arguments 參數(shù)是一個(gè)枚舉數(shù)組,包含著要傳遞給方法 $name 的參數(shù)。
laravel Model的__callStatic實(shí)現(xiàn)的業(yè)務(wù)
new static;
new當(dāng)前model,也就是new User,這個(gè)是static靜態(tài)延遲綁定的使用,可以和“new self;”使用進(jìn)行比較。
call_user_func_array([$instance, $method], $parameters);
主要是這段,call_user_func_array 調(diào)用了new static類即User的where或paginate方法,傳遞 $parameters參數(shù)。
然后,然后,然后,User這個(gè)繼承Model類里面仍然沒(méi)有where或paginate方法,那么使用 Model的__call這魔術(shù)方法。
/**
* 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);
}開始還以為這么處理多了一層魔術(shù)方法,浪費(fèi)效率,想想突然明白了,
User::where();
$user = new User; $user->paginate(15);
代碼是一樣的,只不過(guò)用__callStatic的 new static代替了“new User;”,
用call_user_func_array代替了調(diào)用函數(shù)和傳參,lavarel的簡(jiǎn)潔可見一斑。
繼續(xù)分析,如果調(diào)用的方法是 increment或者decrement,那么使用的是User類的方法。
否則使用 $this->newQuery();
newQuery這個(gè)方法的層級(jí)太深,沒(méi)能理解,不過(guò)看注釋,主要是調(diào)用
'Illuminate\Database\Eloquent\Builder' /** * Get a new query builder for the model's table. * * @return \Illuminate\Database\Eloquent\Builder */ public function newQuery()
Builder這個(gè)類里面的where和paginate方法,就是ORM使用的方法;
其中paginate方法
/**
* Paginate the given query.
*
* @param int $perPage
* @param array $columns
* @param string $pageName
* @param int|null $page
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
*
* @throws \InvalidArgumentException
*/
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
{
$page = $page ?: Paginator::resolveCurrentPage($pageName);
$perPage = $perPage ?: $this->model->getPerPage();
$query = $this->toBase();
$total = $query->getCountForPagination();
$results = $total ? $this->forPage($page, $perPage)->get($columns) : new Collection;
return new LengthAwarePaginator($results, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]);
}paginate調(diào)用最后使用了LengthAwarePaginator類,
所以最后var_dump($user) 是“object(Illuminate\Pagination\LengthAwarePaginator)[306]”
LengthAwarePaginator只是分頁(yè)類,與數(shù)據(jù)層無(wú)關(guān),即Eloquent ORM和分頁(yè)是分離的。
以上就是Lavavel的Eloquent ORM分頁(yè)源碼分析,很多地方有待深入,不過(guò)看一次源碼,提高很大。
文章名稱:Lavavel筆記EloquentORM分頁(yè)源碼分析
本文來(lái)源:http://www.dlmjj.cn/article/gpdggd.html


咨詢
建站咨詢
