借 Xdebug,助你分析 $model->save () 怎么执行的
前言:之前我通过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 协议》,转载必须注明作者和本文链接
:clap: