vr-shopxo-source/thinkphp/library/think/Model.php

1073 lines
25 KiB
PHP
Raw Normal View History

2019-11-11 12:57:06 +00:00
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use InvalidArgumentException;
use think\db\Query;
/**
* Class Model
* @package think
* @mixin Query
* @method \think\Model withAttr(array $name,\Closure $closure) 动态定义获取器
*/
abstract class Model implements \JsonSerializable, \ArrayAccess
{
use model\concern\Attribute;
use model\concern\RelationShip;
use model\concern\ModelEvent;
use model\concern\TimeStamp;
use model\concern\Conversion;
/**
* 是否存在数据
* @var bool
*/
private $exists = false;
/**
* 是否Replace
* @var bool
*/
private $replace = false;
/**
* 是否强制更新所有数据
* @var bool
*/
private $force = false;
/**
* 更新条件
* @var array
*/
private $updateWhere;
/**
* 数据库配置信息
* @var array|string
*/
protected $connection = [];
/**
* 数据库查询对象类名
* @var string
*/
protected $query;
/**
* 模型名称
* @var string
*/
protected $name;
/**
* 数据表名称
* @var string
*/
protected $table;
/**
* 写入自动完成定义
* @var array
*/
protected $auto = [];
/**
* 新增自动完成定义
* @var array
*/
protected $insert = [];
/**
* 更新自动完成定义
* @var array
*/
protected $update = [];
/**
* 初始化过的模型.
* @var array
*/
protected static $initialized = [];
/**
* 是否从主库读取(主从分布式有效)
* @var array
*/
protected static $readMaster;
/**
* 查询对象实例
* @var Query
*/
protected $queryInstance;
/**
* 错误信息
* @var mixed
*/
protected $error;
/**
* 软删除字段默认值
* @var mixed
*/
protected $defaultSoftDelete;
/**
* 全局查询范围
* @var array
*/
protected $globalScope = [];
/**
* 架构函数
* @access public
* @param array|object $data 数据
*/
public function __construct($data = [])
{
if (is_object($data)) {
$this->data = get_object_vars($data);
} else {
$this->data = $data;
}
if ($this->disuse) {
// 废弃字段
foreach ((array) $this->disuse as $key) {
if (array_key_exists($key, $this->data)) {
unset($this->data[$key]);
}
}
}
// 记录原始数据
$this->origin = $this->data;
$config = Db::getConfig();
if (empty($this->name)) {
// 当前模型名
$name = str_replace('\\', '/', static::class);
$this->name = basename($name);
if (Container::get('config')->get('class_suffix')) {
$suffix = basename(dirname($name));
$this->name = substr($this->name, 0, -strlen($suffix));
}
}
if (is_null($this->autoWriteTimestamp)) {
// 自动写入时间戳
$this->autoWriteTimestamp = $config['auto_timestamp'];
}
if (is_null($this->dateFormat)) {
// 设置时间戳格式
$this->dateFormat = $config['datetime_format'];
}
if (is_null($this->resultSetType)) {
$this->resultSetType = $config['resultset_type'];
}
if (!empty($this->connection) && is_array($this->connection)) {
// 设置模型的数据库连接
$this->connection = array_merge($config, $this->connection);
}
if ($this->observerClass) {
// 注册模型观察者
static::observe($this->observerClass);
}
// 执行初始化操作
$this->initialize();
}
/**
* 获取当前模型名称
* @access public
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* 是否从主库读取数据(主从分布有效)
* @access public
* @param bool $all 是否所有模型有效
* @return $this
*/
public function readMaster($all = false)
{
$model = $all ? '*' : static::class;
static::$readMaster[$model] = true;
return $this;
}
/**
* 创建新的模型实例
* @access public
* @param array|object $data 数据
* @param bool $isUpdate 是否为更新
* @param mixed $where 更新条件
* @return Model
*/
public function newInstance($data = [], $isUpdate = false, $where = null)
{
return (new static($data))->isUpdate($isUpdate, $where);
}
/**
* 创建模型的查询对象
* @access protected
* @return Query
*/
protected function buildQuery()
{
// 设置当前模型 确保查询返回模型对象
$query = Db::connect($this->connection, false, $this->query);
$query->model($this)
->name($this->name)
->json($this->json, $this->jsonAssoc)
->setJsonFieldType($this->jsonType);
if (isset(static::$readMaster['*']) || isset(static::$readMaster[static::class])) {
$query->master(true);
}
// 设置当前数据表和模型名
if (!empty($this->table)) {
$query->table($this->table);
}
if (!empty($this->pk)) {
$query->pk($this->pk);
}
return $query;
}
/**
* 获取当前模型的数据库查询对象
* @access public
* @param Query $query 查询对象实例
* @return $this
*/
public function setQuery($query)
{
$this->queryInstance = $query;
return $this;
}
/**
* 获取当前模型的数据库查询对象
* @access public
* @param bool|array $useBaseQuery 是否调用全局查询范围(或者指定查询范围名称)
* @return Query
*/
public function db($useBaseQuery = true)
{
if ($this->queryInstance) {
return $this->queryInstance;
}
$query = $this->buildQuery();
// 软删除
if (property_exists($this, 'withTrashed') && !$this->withTrashed) {
$this->withNoTrashed($query);
}
// 全局作用域
if (true === $useBaseQuery && method_exists($this, 'base')) {
call_user_func_array([$this, 'base'], [ & $query]);
}
$globalScope = is_array($useBaseQuery) && $useBaseQuery ? $useBaseQuery : $this->globalScope;
if ($globalScope && false !== $useBaseQuery) {
$query->scope($globalScope);
}
// 返回当前模型的数据库查询对象
return $query;
}
/**
* 初始化模型
* @access protected
* @return void
*/
protected function initialize()
{
if (!isset(static::$initialized[static::class])) {
static::$initialized[static::class] = true;
static::init();
}
}
/**
* 初始化处理
* @access protected
* @return void
*/
protected static function init()
{}
/**
* 数据自动完成
* @access protected
* @param array $auto 要自动更新的字段列表
* @return void
*/
protected function autoCompleteData($auto = [])
{
foreach ($auto as $field => $value) {
if (is_integer($field)) {
$field = $value;
$value = null;
}
if (!isset($this->data[$field])) {
$default = null;
} else {
$default = $this->data[$field];
}
$this->setAttr($field, !is_null($value) ? $value : $default);
}
}
/**
* 更新是否强制写入数据 而不做比较
* @access public
* @param bool $force
* @return $this
*/
public function force($force = true)
{
$this->force = $force;
return $this;
}
/**
* 判断force
* @access public
* @return bool
*/
public function isForce()
{
return $this->force;
}
/**
* 新增数据是否使用Replace
* @access public
* @param bool $replace
* @return $this
*/
public function replace($replace = true)
{
$this->replace = $replace;
return $this;
}
/**
* 设置数据是否存在
* @access public
* @param bool $exists
* @return $this
*/
public function exists($exists)
{
$this->exists = $exists;
return $this;
}
/**
* 判断数据是否存在数据库
* @access public
* @return bool
*/
public function isExists()
{
return $this->exists;
}
/**
* 保存当前数据对象
* @access public
* @param array $data 数据
* @param array $where 更新条件
* @param string $sequence 自增序列名
* @return bool
*/
public function save($data = [], $where = [], $sequence = null)
{
if (is_string($data)) {
$sequence = $data;
$data = [];
}
if (!$this->checkBeforeSave($data, $where)) {
return false;
}
$result = $this->exists ? $this->updateData($where) : $this->insertData($sequence);
if (false === $result) {
return false;
}
// 写入回调
$this->trigger('after_write');
// 重新记录原始数据
$this->origin = $this->data;
$this->set = [];
return true;