本期要點
深入了解php函數的各種輔助函數 php核心語法:函數
理解什么是php函數函數, …$var, PHP5.6新特性介紹
php函數函數的用法 PHP: compact – Manual
php函數函數的用法 PHP: list – Manual
PHPphp函數
開始之前
本期說的是SQL中的查詢語句, 由于復雜程度和多個類之間的關聯性不是Connector篇那么簡單, 故此, 這一回需要一口氣講解Builder類, Grammar類, 還有php函數類, 當然, 只是查詢部分
Builder.php
-
請求構建器, 所有類之間的橋梁
<?php /** * 請求構建器 */ class Builder { // 連接數據庫, Connector類 protected $connector; // 生成SQL語法,Grammar類 protected $grammar; // 連接的Model, Model類 protected $model; // SQL查詢語句中條件的值 // 雖然列出了全部, 但本教程只實現了where,其余的因為懶(理直氣壯),請自行實現, 邏輯和where函數大致 protected $bindings = [ 'select' => [], 'join' => [], 'where' => [], 'having' => [], 'order' => [], 'union' => [], ]; // select 語法想要查看的字段 public $columns; // 過濾重復值 public $distinct = false; // 需要查詢的表 public $from; // 所有join 語法 public $joins; // 所有where 語法 public $wheres; // group 語法 public $groups; // having 語法 public $havings; // order by 語法 public $orders; // 限制數據庫返回的數據量, limit語法 public $limit; // 需要略過的數據量, offset語法 public $offset; // 數據寫保護, 開啟后該條數據無法刪除或改寫 public $writeLock = false;
接下來是函數
-
_construct – 生成實例后第一步要干嘛
function construct() { // 新建兩個實例 // 如果已經理解Connector的原理后自然明白這個Connector實例已經聯通了數據庫 $this->connector = new Connector; $this->grammar = new Grammar; }
-
select – 選擇想看到的column, 默認為全部, 即 ‘*’
public function select($columns = ['*']) { // $columns只能存入數組, 所以需要判定, 如果不是, 將所有參數合成一個數組再存入 // 這是一個更人性化的設定, 用戶可以選擇以下兩種調用方式 // select(['first_name', 'last_name']), 以數組的方式 // select('first_name', 'last_name'), 以參數的方式 // 最后一點, 你可以發現所有函數最后都會存入對應的Builder屬性中 // 這和你在做飯前先處理材料是同一個道理, 也就是預處理 $this->columns = is_array($columns) ? $columns : func_get_args(); return $this; }
-
distinct – 過濾重復值
public function distinct() { // 開啟過濾 $this->distinct = true; return $this; }
-
from – 設置表名
public function from($table) { $this->from = $table; return $this; }
-
join – 連接兩個表的join語法, 默認為inner join
/** * @param string $table 需要連接的副表名 * 為什么主鍵和外鍵可以單個或數組呢 * 原因是join語法可以on多個鍵 * @param string/array $foregin 外鍵 * @param string/array $primary 主鍵 * @param string $type 連接方式, 默認inner * @return Builder 返回Builder實例 */ public function join($table, $foregin , $primary, $type = 'inner') { // 判定外鍵變量的數據類型 if(is_array($foregin)) { // 如果是數組, 循環加上副表名在前頭 foreach($foregin as &$f) $f = $table.".".$f; }else { // 反之, 不需循環直接加 $foregin = $table.".".$foregin; } // 與$foreign的邏輯同理 if(is_array($primary)) { foreach($primary as &$p) $p = $this->from.".".$p; }else { $primary = $this->from.".".$primary; } // 將所有經過處理的參數收入$joins待用 $this->joins[] = (object)[ 'from' => $this->from, 'table' => $table, 'foregin' => $foregin, 'primary' => $primary, 'type' => $type ]; // 返回Builder實例 return $this; }
-
join的各種變形, 只實現常見的三種join, 其余請自行添加
// 所有邏輯同join(), 不過這是left join public function leftJoin($table, $foregin , $primary) { return $this->join($table, $foregin , $primary, 'left'); } // 所有邏輯同join(), 不過這是right join public function rightJoin($table, $foregin , $primary) { return $this->join($table, $foregin , $primary, 'right'); }
-
addBinding – 儲存各種sql條件所附帶的值
/** * @param string/array $value 字段匹配的值 * @param string $type 條件類型, 默認為where, 具體查看$bindings */ public function addBinding($value, $type = 'where') { // 如果$type并不是$bindings的鍵, 跳出錯誤 if (!array_key_exists($type, $this->bindings)) throw new InvalidArgumentException("Invalid binding type: {$type}."); // 如果$value是數組,將其與之前存入的值整合為一維數組 if (is_array($value)) $this->bindings[$type] = array_values(array_merge($this->bindings[$type], $value)); // 反之, 直接存入最后一位即可 else $this->bindings[$type][] = $value; // 返回Builder實例 return $this; }
-
where – sql中的條件, where語法
where()有兩種不同的調用方式
接下來多個函數都有兩種調用方式, 請從之后的代碼邏輯中自行領悟
以參數的方式, 默認為’=’
Actor::select('first_name', 'last_name') ->where('first_name', 'NICK') ->where('last_name','!=', 'WAHLBERG') ->first()
以數組的方式, 這方式有局限性, 僅能匹配 字段等于值 的情況
Actor::select('first_name', 'last_name') ->where(['first_name'=> 'NICK', 'last_name'=> 'WAHLBERG']) ->first()
接下來看代碼
public function where($column, $operator = null, $value = null, $boolean = 'and') { // 判定$column是否為數組 if (is_array($column)) { // 如果是數組, 循環再調用本函數,where() foreach ($column as $key => $value) $this->where($key, "=", $value, $boolean); }else { // 反之, 判定參數數量和$value是否為空, 如果為真,這意味著用戶省略了'=',自動添加 if(func_num_args() == 2 || is_null($value)) list($operator, $value) = ['=', $operator]; // 最簡單原始的條件查詢, 所以$type值為Basic $type = "Basic"; // 將處理過的條件存入$wheres $this->wheres[] = compact('type', 'column', 'operator', 'value', 'boolean'); // 將字段需要匹配的值存入$bindings中的where $this->addBinding($value, 'where'); } // 返回Builder實例 return $this; }
-
where的各種變形
// 所有邏輯同where(), 不過這是or where public function orWhere($column, $operator = null, $value = null) { return $this->where($column, $operator, $value, 'or'); } /** * where in 語法, 字段匹配多個值 * @param string $column 字段 * @param array $values 一組字段需匹配的值 * @param string $boolean 默認為and * @param boolean $not 默認為假, 真為排除所有$value里的數據 * @return Builder 返回Builder實例 */ public function whereIn($column, $values, $boolean = 'and', $not = false) { // 判定條件查詢的類型, false = where in ($value),true = where not in ($value) $type = $not ? 'NotIn' : 'In'; // 將條件存入$wheres $this->wheres[] = compact('type', 'column', 'values', 'boolean'); // 循環將字段需要匹配的值存入$bindings中的where foreach ($values as $value) $this->addBinding($value, 'where'); // 返回Builder實例 return $this; } // 所有邏輯同whereIn(), 不過這是or where in public function orWhereIn($column, $values) { return $this->whereIn($column, $values, 'or'); } // 所有邏輯同whereIn(), 不過這是and where not in public function whereNotIn($column, $values, $boolean = 'and') { return $this->whereIn($column, $values, $boolean, true); } // 所有邏輯同whereNotIn(), 不過這是or where not in public function orWhereNotIn($column, $values) { return $this->whereNotIn($column, $values, 'or'); } /** * where $coulmn is null 語法, 搜索字段為空的數據 * @param string $column 字段 * @param string $boolean 默認為and * @param boolean $not 默認為假, 真為排除所有字段為空的數據 * @return Builder 返回Builder實例 */ public function whereNull($column, $boolean = 'and', $not = false) { // 判定條件查詢的類型, false = where $column is null,true = where $column is not null $type = $not ? 'NotNull' : 'Null'; // 將條件存入$wheres $this->wheres[] = compact('type', 'column', 'boolean'); // 返回Builder實例 return $this; } // 所有邏輯同whereNull(), 不過這是or where $column is null public function orWhereNull($column) { return $this->whereNull($column, 'or'); } // 所有邏輯同whereNull(), 不過這是and where $column is not null public function whereNotNull($column, $boolean = 'and') { return $this->whereNull($column, $boolean, true); } // 所有邏輯同whereNotNull(), 不過這是or where $column is not null public function orWhereNotNull($column) { return $this->whereNotNull($column, 'or'); }
-
orderBy – order by 語句, 決定返回的數據排列
/** * @param string/array $column 字段 * @param string $direction 排序,默認為asc, 順序 * @return Builder 返回Builder實例 */ public function orderBy($column, $direction = 'asc') { // 局限性在于必須聲明順序或逆序 if(is_array($column)) { foreach ($column as $key => $value) $this->orderBy($key, $value); }else { // 簡單判定后直接存入$orders, $direction輸入錯誤不跳錯誤直接選擇順序 $this->orders[] = [ 'column' => $column, 'direction' => strtolower($direction) == 'desc' ? 'desc' : 'asc', ]; } // 返回Builder實例 return $this; }
輔助函數 – array_flatten
這是我自己寫的一個函數, 用于撫平php函數
什么意思呢, 就是將多維數組整成一維數組function array_flatten(array $array) { $return = array(); array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; }); return $return; }
例子
$a = array('this', 'is', array('a', 'multidimentional', array('array') ), 'to', 'make', 'the', 'tutotal', array('more', 'easier', 'to', 'understand') ); dd(array_flatten($a));
返回
array (size=13) 0 => string 'this' (length=4) 1 => string 'is' (length=2) 2 => string 'a' (length=1) 3 => string 'multidimentional' (length=16) 4 => string 'array' (length=5) 5 => string 'to' (length=2) 6 => string 'make' (length=4) 7 => string 'the' (length=3) 8 => string 'tutotal' (length=7) 9 => string 'more' (length=4) 10 => string 'easier' (length=6) 11 => string 'to' (length=2) 12 => string 'understand' (length=10)
-
groupBy – group by 語句, 整合數據
/** * @param string/array $groups 字段 * @return Builder 返回Builder實例 */ public function groupBy(...$groups) { if(empty($this->groups)) $this->groups = []; $this->groups = array_merge($this->groups, array_flatten($groups)); // 返回Builder實例 return $this; }
-
limit – 限制返回的數據量, sqlsrv的寫法不同, 有興趣知道的可以留言
public function limit($value) { // 如果$value大于零這條函數才生效 if ($value >= 0) $this->limit = $value; return $this; } // limit函數的別名, 增加函數鏈的可讀性 public function take($value) { return $this->limit($value); }
-
offset – 跳過指定的數據量, sqlsrv的寫法不同, 有興趣知道的可以留言
public function offset($value) { // 如果$value大于零這條函數才生效 if ($value >= 0) $this->offset = $value; return $this; } // offset函數的別名, 增加函數鏈的可讀性 public function skip($value) { return $this->offset($value); }
-
get – 讀取數據庫數據
重頭戲來了, 之前所有的函數都是返回Builder實例的,這意味著可再編輯
這是一個總結, 將前端的函數鏈請求一并處理了// 返回一組數據庫數據, 可以在這里設定想返回的字段, 但是select()的優先度最高 public function get($columns = ['*']) { // 如果Builder的$columns依然為空, 那么就用該函數的$columns, 反之則使用select()所聲明的字段 if (is_null($this->columns)) $this->columns = $columns; // 如果Builder的$orders依然為空, 那么就默認第一個字段順序 // 發現一個莫名的bug, 可能是我理解錯了, 不加 order by 1數據返回竟然不是按照主鍵(第一個字段)排序 // 所以以防萬一加一個默認 if (is_null($this->orders)) $this->orderBy(1); // 將Grammar類生成的語句,和處理過的字段所對應的值,都交給Connector類, 讓它與數據庫進行通信,返回數據 // 注意這里的三個函數 // read() 不用說Connector篇介紹過了 // compileSelect()是用來編譯生成查詢語句 // getBindings()用來獲取收在$bindings中條件的值, 下方會有說明 $results = $this->connector->read($this->grammar->compileSelect($this), $this->getBindings()); // 返回一組數據庫數據,如果查詢為空,返回空數組 // cast()下方會有說明 return $this->cast($results); } // get函數的別名, 增加函數鏈的可讀性 public function all($columns = ['*']) { return $this->get($columns); }
-
getBindings – 返回所有$bindings中的值
public function getBindings() { // 撫平多維數組成一維數組后再返回 return array_flatten($this->bindings); }
-
cast – 轉化返回的數據類型為自身的Model子類
在基本思路篇的最終效果小節有提到過數據的可操作性, 核心代碼就是這里
如果看不明白這里沒關系, 暫時跳過, 等看完Model.php就能理解了(吧?)public function cast($results){ // 獲取Model子類的名稱 $class = get_class($this->model); // 新建一個Model子類 $model = new $class(); // 如果獲得的數據庫數據是數組 if (gettype($results)=="array") { $arr = []; // 循環數據 foreach ($results as $result) // 再調用本函數 $arr[] = $this->cast($result); // 返回經過轉化的數據數組 return $arr; // 如果獲得的數據庫數據是對象 }elseif(gettype($results)=="object"){ // 存入數據對象 $model->setData($results); // 加入主鍵或unique key以實現數據的可操作性 // 如果表存在主鍵和返回的數據中有主鍵的字段 if($model->getIdentity() && isset($results->{$model->getIdentity()})) { $model->where($model->getIdentity(), $results->{$model->getIdentity()}); // 如果表存在unique key和返回的數據中有unique key的字段 }elseif($model->getUnique() && array_check($model->getUnique(),$results)) { foreach ($model->getUnique() as $key) $model->where($key, $results->$key); // 改寫和刪除操作僅僅在符合以上兩種條件其中之一的時候 // 反之, 開啟寫保護不允許改寫 }else { // 其實還可以考慮直接復制query // 但變數太多干脆直接一棍子打死 $model->getBuilder()->writeLock = true; } // 返回該實例 return $model; } // 如果轉化失敗返回false return false; }
-
first – 僅取頭一條數據, 所以返回的是對象, 而get返回的是數組,里頭多條對象
/** * @param array $columns 如果Builder的$columns依然為空, 那么就用該函數的$columns, 反之則使用select()所聲明的字段 * @return boolean/Model 查詢為空返回false, 反之則返回附帶數據的表類 */ public function first($columns = ['*']) { $results = $this->take(1)->get($columns); return empty($results) ? false : $results[0]; }
-
setModel – 設置Model實例
public function setModel(Model $model) { $this->model = $model; return $this; }
告一段落, 接下來編譯SQL語句, Grammar類
Grammar.php
-
根據經過處理后存在Builder實例屬性中的值進行編譯
-
編譯是一部分一部分語法慢慢編譯的, 最后在總結起來
<?php /** * 數據庫語法生成 */ class Grammar { // 構建查詢語句所可能出現的各種SQL語法 // 注意, 它們的順序是對應著各自在SQL語句中合法的位置 // sqlsrv略微不同 protected $selectComponents = [ 'distinct', 'columns', 'from', 'joins', 'wheres', 'groups', 'orders', 'limit', 'offset', ];
-
concatenate – ?排除編譯后可能存在空的值,然后連接整句SQL語句
protected function concatenate($segments) { return implode(' ', array_filter($segments, function ($value) { return (string) $value !== ''; })); }
-
compileSelect – 編譯SQL查詢語句
// 還記得Builder->get()中的compileSelect()嗎? public function compileSelect(Builder $query) { // concatenate()排除編譯后可能存在空的值,然后連接整句SQL語句 // 去掉可能存在的前后端空格再返回 return trim($this->concatenate($this->compileComponents($query))); }
-
compileComponents – 循環$selectComponents, 根據不同的語法局部編譯對應的語句
protected function compileComponents(Builder $query) { $sql = []; // 循環$selectComponents foreach ($this->selectComponents as $component) { // 如果Builder實例中對應的函數曾經被調用,那意味著對應的語法非空 if (!is_null($query->$component)) { $method = 'compile'.ucfirst($component); // 編譯該語法并將之收入$sql $sql[$component] = $this->$method($query, $query->$component); } } // 返回$sql數組 return $sql; }
-
compileDistinct – 編譯distinct語句
protected function compileDistinct(Builder $query, $distinct) { return $distinct ? 'select distinct' : 'select'; }
-
compileLimit – 編譯limit語句
protected function compileLimit(Builder $query, $limit) { return "limit $limit"; }
-
compileOffset – 編譯offset語句
protected function compileOffset(Builder $query, $offset) { return "offset $offset"; }
-
compileColumns – 編譯需查詢的字段
protected function compileColumns(Builder $query, $columns) { return implode(', ', $columns); }
-
compileFrom – 編譯生成表名
protected function compileFrom(Builder $query, $table) { return 'from '.$table; }
-
compileJoins – 編譯join語句
protected function compileJoins(Builder $query, $joins) { $sql = []; foreach ($joins as $join) { // 如果存在多個副鍵和主鍵 if(is_array($join->foregin) && is_array($join->primary)) { $on = []; // 循環鍵的數量, 將之與對應的主鍵組合 for($i=0; $i<sizeof($join->foregin); $i++) $on[] = $join->foregin[$i]." = ".$join->primary[$i]; // 最后再將所有句子用and連接 $on = implode(' and ', $on); } else { //反之, 直接連接即可 $on = "$join->foregin = $join->primary"; } // 附上join的類型和副表 $sql[] = trim("{$join->type} join {$join->table} on $on"); } // 連接再返回 return implode(' ', $sql); }
-
compileWheres – 編譯where語句
protected function compileWheres(Builder $query) { $sql = []; // 類似與compileComponents(), 循環Builder實例中的$wheres foreach ($query->wheres as $where) { // 根據不同的$type來進行編譯 $method = "where{$where['type']}"; // 返回的部分語句先收入數組 $sql[] = $where['boolean'].' '.$this->$method($query, $where); } // 最后將$sql數組連接起來, 刪掉最前面的and或or在返回 return 'where '.preg_replace('/and |or /i', '', implode(" ", $sql), 1); }
-
whereBasic – 編譯最基本的where用法
protected function whereBasic(Builder $query, $where) { // 檢測$where[column]是否存在小數點 // 是, 就意味著前綴已經附帶了表名 // 否, 為之后的字段添上表名 // 因為join存在副表, 所以部分$where可能有附帶表名, 這時候就不用添加了 $table = !preg_match('/./', $where['column']) ? $query->from."." : ''; // 返回添上表名的字段,和表達式, 再一個問號 // 為何使用問號而不是:變量名? 因為:變量名存在太多局限性,不能標點符號,不能數字開頭 return $table.$where['column'].' '.$where['operator'].' ?'; }
-
whereIn – 編譯where in用法
protected function whereIn(Builder $query, $where) { // 檢測$where[column]是否存在小數點, 同理whereBasic() $table = !preg_match('/./', $where['column']) ? $query->from."." : ''; // 有多少個匹配值那就連接多少個問號 $values = implode(', ', array_fill(0, sizeof($where['values']), '?')); // 返回where in 語句 return $table.$where['column'].' in ('.$values.')'; }
-
whereNotIn – 編譯where not in用法
protected function whereNotIn(Builder $query, $where) { // 檢測$where[column]是否存在小數點, 同理whereBasic() $table = !preg_match('/./', $where['column']) ? $query->from."." : ''; // 有多少個匹配值那就連接多少個問號 $values = implode(', ', array_fill(0, sizeof($where['values']), '?')); // 返回where not in 語句 return $table.$where['column'].' not in ('.$values.')'; }
-
whereNull – 編譯where null用法
protected function whereNull(Builder $query, $where) { // 檢測$where[column]是否存在小數點, 同理whereBasic() $table = !preg_match('/./', $where['column']) ? $query->from."." : ''; // 返回where is null 語句 return $table.$where['column'].' is null'; }
-
whereNotNull – 編譯where not null用法
protected function whereNotNull(Builder $query, $where) { // 檢測$where[column]是否存在小數點, 同理whereBasic() $table = !preg_match('/./', $where['column']) ? $query->from."." : ''; // 返回where is not null 語句 return $table.$where['column'].' is not null'; }
-
compileGroups – 編譯group by語句
protected function compileGroups(Builder $query, $groups) { // 連接$groups, 返回group by語句 return 'group by '.implode(', ', $groups); }
-
compileOrders – 編譯order by語句
protected function compileOrders(Builder $query, $orders) { // 連接每一個$order與其$direction, 然后返回order by語句 return 'order by '.implode(', ', array_map(function ($order) { return $order['column'].' '.$order['direction']; }, $orders)); }
Grammar告一段落, 接下來是php函數, Model類, 一個魔術世界
Model.php
-
數據庫表的依賴對象
-
作為數據的出口, 數據就在這里進行修飾
-
各種魔術方法用得飛起, 使用之前請先理解魔術方法是什么
<?php /** * 入口文件, 數據庫表的父類 */ class Model { // SQL命令構建器, Builder類 protected $builder; // 數據庫返回的數據存在這里 protected $data; // 數據庫表名, 選填, 默認為類名 protected $table; // 主鍵, 二選一($unique) protected $identity; // unique key, 二選一($identity) protected $unique;
-
getTable – 獲取數據庫表名, 沒有設置返回false
public function getTable() { return isset($this->table) ? $this->table : false; }
-
getIdentity – 獲取主鍵名, 沒有返回假
public function getIdentity() { return isset($this->identity) ? $this->identity : false; }
-
getUnique – 獲取unique key名, 沒有返回假
public function getUnique() { // 檢測是否存在unique key, 不存在返回假, 存在就在檢查是否數組, 不是就裝入數組再返回 return isset($this->unique) ? is_array($this->unique) ? $this->unique : [$this->unique] : false; }
-
check – 檢查必須預設的實例屬性
public function check() { // 如果數據庫表的名稱和Model的子類相同,可以選擇不填,默認直接取類的名稱 if(!$this->getTable()) $this->table = get_class($this); // 跳出提醒必須設置$identity或$unique其中一項 if(!$this->getIdentity() && !$this->getUnique()) throw new Exception('One of $identity or $unique should be assigned in Model "'.get_called_class().'"'); }
-
set/getBuilder – 設置或讀取Builder實例
// 設置Builder實例 public function setBuilder(Builder $builder) { $this->builder = $builder; return $this; } // 獲取Builder實例 public function getBuilder() { return $this->builder; }
-
setData – 設置數據庫數據
public function setData($data) { $this->data = $data; return $this; }
-
construct – 創建實例后的第一步
function construct() { // 檢查設定是否正確 $this->check(); // 新建一個Builder實例 $this->setBuilder(new Builder); // 設置構建器的主表名稱 $this->getBuilder()->from($this->table); // 將Model實例帶入Builder $this->getBuilder()->setModel($this); }
魔術方法
-
callphp函數 – 如果找不到php函數函數的時候自動運行下面的邏輯
static public function callStatic($method, $args = null) { // 這是一個偽靜態, 創建一個實例 $instance = new static; // 在$instance->builder之中, 尋找函數$method, 并附上參數$args return call_user_func_array([$instance->builder, $method], $args); }
-
call – 如果找不到函數的時候自動運行下面的邏輯
public function call($method, $args) { // 在$this->builder之中, 尋找函數$method, 并附上參數$args return call_user_func_array([$this->builder, $method], $args); }
-
debugInfo – 在php函數的時候隱藏多余的信息, 只留下數據庫返回的數據
public function debugInfo() { // 也不懂算不算bug, 該方法強制要求返回的數據類型必須是array數組 // 但是就算我強行轉換(casting)后返回的數據依然是對象(object) return (array)$this->data; }
-
get – 當調用對象的屬性時, 強制調用這個魔術方法
// 為了避免局外人可以訪問Model類的屬性 // 為了避免對象屬性和表的字段名字相同 public function get($field) { // 如果調用的屬性是Model類內的邏輯 // 直接返回該屬性的值 if(get_called_class()==="Model") return $this->$field; // 反之, 則檢查$data內是否存在該屬性, 沒有的話跳出錯誤 if(!isset($this->data->$field)) throw new Exception("column '$field' is not exists in table '$this->table'"); // 如果存在,由于返回的數據都是存在$data里, 所以要這樣調用 return $this->data->$field; }
-
set – 當想修改的對象屬性時, 強制調用這個魔術方法
public function set($field, $value) { // 如果調用的屬性是Model類內的邏輯 // 直接賦值該屬性 if(get_called_class()==="Model") return $this->$field = $value; // 反之, 則檢查$data內是否存在該屬性, 沒有的話跳出錯誤 if(!isset($this->data->$field)) throw new Exception("column '$field' is not exists in table '$this->table'"); // 如果存在,由于返回的數據都是存在$data里, 所以要這樣賦值 return $this->data->$field = $value; }
進階的Buider類封裝沒錯, 我又把Builder(微)封裝了
-
find – 使用主鍵查尋數據
/** * @param int $id 主鍵 * @return Model subclass 返回一個Model的子類數據 */ public static function find($id) { // 這是一個偽靜態, 創建一個實例 $self = new static; // 該函數只適用于設置了主鍵的表, 如果沒有設置, 跳出錯誤 if(!$self->getIdentity()) throw new Exception("Table's identity key should be assgined"); return $self->where($self->identity, $id)->first(); }
還有更多, 看心情更…
本期疑問
1.) 缺少的Builder函數如果有人愿意提供例子就好了, 進階復雜的語句那就更好了, 直接寫然后再分享給我那就最好了
2.) 有些函數或結構可能沒有效率或者白白添加服務器壓力, 但我寫的順了可能沒看見, 請指出
3.) 有人能告訴我laravel是怎么解決php函數 2100個最大參數(bind)的問題嗎? 源代碼把我看蒙了