前言:之前我通過Laravel的測試用例分析過,但是隻能算是會用,現在帶大家看看它的原理
語句:update system_parameters
set value
= "omgzui" where id
= 5
Laravel版本:5.5
超長程式碼警告 ⚠️
// update `system_parameters` set `value` = "omgzui" where `id` = 5
public function save(array $options = [])
{
// Get a new query builder instance for the connection.
$query = $this->newModelQuery();
// 執行失敗就直接返回false
if ($this->fireModelEvent('saving') === false) {
return false;
}
// 已經存在就更新
if ($this->exists) {
$saved = $this->isDirty() ? $this->performUpdate($query) : true;
}
// 不存在就新增,按自增ID
else {
$saved = $this->performInsert($query);
if (! $this->getConnectionName() &&
$connection = $query->getConnection()) {
$this->setConnection($connection->getName());
}
}
// 成功之後完成一些附加操作
if ($saved) {
$this->finishSave($options);
}
return $saved;
}
// 獲取資料庫連線例項
public function connection($name = null)
{
list($database, $type) = $this->parseConnectionName($name);
$name = $name ?: $database;
// 還沒有連線例項就建立一個
if (! isset($this->connections[$name])) {
$this->connections[$name] = $this->configure(
$this->makeConnection($database), $type
);
}
return $this->connections[$name];
}
// 查詢構建例項
protected function newBaseQueryBuilder()
{
$conn = $this->getConnection();
$grammar = $conn->getQueryGrammar();
$builder = new QueryBuilder($conn, $grammar, $conn->getPostProcessor());
if ($this->duplicateCache) {
$builder->enableDuplicateCache();
}
return $builder;
}
// 通過比較原始資料和post資料返回改變的資料
public function getDirty()
{
$dirty = [];
foreach ($this->getAttributes() as $key => $value) {
if (! $this->originalIsEquivalent($key, $value)) {
$dirty[$key] = $value;
}
}
return $dirty;
}
// 拼接sql
// $boolean = "and"
// $column = "id"
// $operator = "="
// $value = {int} 5
public function where($column, $operator = null, $value = null, $boolean = 'and')
{
if ($column instanceof Closure) {
$column($query = $this->model->newModelQuery());
$this->query->addNestedWhereQuery($query->getQuery(), $boolean);
} else {
$this->query->where(...func_get_args());
}
return $this;
}
// $this->query->where(...func_get_args());
public function where($column, $operator = null, $value = null, $boolean = 'and')
{
// 處理欄位陣列
if (is_array($column)) {
return $this->addArrayOfWheres($column, $boolean);
}
// 處理操作符
list($value, $operator) = $this->prepareValueAndOperator(
$value, $operator, func_num_args() == 2
);
// 處理欄位閉包
if ($column instanceof Closure) {
return $this->whereNested($column, $boolean);
}
// 給省略操作符的預設加上 "="
if ($this->invalidOperator($operator)) {
list($value, $operator) = [$operator, '='];
}
// 值是閉包。處理子查詢
if ($value instanceof Closure) {
return $this->whereSub($column, $operator, $value, $boolean);
}
// 值為空,預設為null
if (is_null($value)) {
return $this->whereNull($column, $boolean, $operator !== '=');
}
// 處理欄位是json格式
if (Str::contains($column, '->') && is_bool($value)) {
$value = new Expression($value ? 'true' : 'false');
}
// 簡單查詢whereBasic,主要是區分whereIn、whereNull這種
$type = 'Basic';
$this->wheres[] = compact(
'type', 'column', 'operator', 'value', 'boolean'
);
if (! $value instanceof Expression) {
$this->addBinding($value, 'where');
}
return $this;
}
// 更新
public function update(array $values)
{
// $sql = rtrim("update {$table}{$joins} set $columns $where");
// update `system_parameters` set `value` = ? where `id` = ?
$sql = $this->grammar->compileUpdate($this, $values);
return $this->connection->update($sql, $this->cleanBindings(
$this->grammar->prepareBindingsForUpdate($this->bindings, $values)
));
}
// 多維陣列變一維
public static function flatten($array, $depth = INF)
{
$result = [];
foreach ($array as $item) {
$item = $item instanceof Collection ? $item->all() : $item;
if (! is_array($item)) {
$result[] = $item;
} elseif ($depth === 1) {
$result = array_merge($result, array_values($item));
} else {
$result = array_merge($result, static::flatten($item, $depth - 1));
}
}
return $result;
}
// SQL最終執行
// $bindings = {array} [2]
// 0 = ""omgzui""
// 1 = {int} 5
// $query = "update `system_parameters` set `value` = ? where `id` = ?"
public function affectingStatement($query, $bindings = [])
{
return $this->run($query, $bindings, function ($query, $bindings) {
if ($this->pretending()) {
return 0;
}
// 宣告語句
$statement = $this->getPdo()->prepare($query);
// 語句預處理繫結
$this->bindValues($statement, $this->prepareBindings($bindings));
$statement->execute();
// 修改了幾條資料
$this->recordsHaveBeenModified(
($count = $statement->rowCount()) > 0
);
return $count;
});
}
protected function run($query, $bindings, Closure $callback)
{
$this->reconnectIfMissingConnection();
$start = microtime(true);
// 重連機制
try {
$result = $this->runQueryCallback($query, $bindings, $callback);
} catch (QueryException $e) {
$result = $this->handleQueryException(
$e, $query, $bindings, $callback
);
}
// 記錄日誌,同時廣播
$this->logQuery(
$query, $bindings, $this->getElapsedTime($start)
);
return $result;
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結