升级ThinkPHP版本

This commit is contained in:
Anyon 2021-01-11 11:55:23 +08:00
parent 988532dc3f
commit dd56cd470e
26 changed files with 191 additions and 95 deletions

View File

@ -536,17 +536,17 @@
}, },
{ {
"name": "topthink/framework", "name": "topthink/framework",
"version": "v6.0.5", "version": "v6.0.6",
"version_normalized": "6.0.5.0", "version_normalized": "6.0.6.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/top-think/framework.git", "url": "https://github.com/top-think/framework.git",
"reference": "85625d984f5c96699dc27d384869f206c3aec1cc" "reference": "dd265d9e962da2c033a45190b839d5538770a760"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/top-think/framework/zipball/85625d984f5c96699dc27d384869f206c3aec1cc", "url": "https://api.github.com/repos/top-think/framework/zipball/dd265d9e962da2c033a45190b839d5538770a760",
"reference": "85625d984f5c96699dc27d384869f206c3aec1cc", "reference": "dd265d9e962da2c033a45190b839d5538770a760",
"shasum": "", "shasum": "",
"mirrors": [ "mirrors": [
{ {
@ -572,7 +572,7 @@
"mockery/mockery": "^1.2", "mockery/mockery": "^1.2",
"phpunit/phpunit": "^7.0" "phpunit/phpunit": "^7.0"
}, },
"time": "2020-10-26T07:18:00+00:00", "time": "2021-01-10T15:35:54+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -601,11 +601,7 @@
"framework", "framework",
"orm", "orm",
"thinkphp" "thinkphp"
], ]
"support": {
"issues": "https://github.com/top-think/framework/issues",
"source": "https://github.com/top-think/framework/tree/v6.0.5"
}
}, },
{ {
"name": "topthink/think-helper", "name": "topthink/think-helper",
@ -660,17 +656,17 @@
}, },
{ {
"name": "topthink/think-orm", "name": "topthink/think-orm",
"version": "v2.0.34", "version": "v2.0.35",
"version_normalized": "2.0.34.0", "version_normalized": "2.0.35.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/top-think/think-orm.git", "url": "https://github.com/top-think/think-orm.git",
"reference": "57f9b98895b0ff4ae7b7b75e51456fd8cb8fb629" "reference": "f0bba0b15610d4015655ff6f07ea3d639212076f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/top-think/think-orm/zipball/57f9b98895b0ff4ae7b7b75e51456fd8cb8fb629", "url": "https://api.github.com/repos/top-think/think-orm/zipball/f0bba0b15610d4015655ff6f07ea3d639212076f",
"reference": "57f9b98895b0ff4ae7b7b75e51456fd8cb8fb629", "reference": "f0bba0b15610d4015655ff6f07ea3d639212076f",
"shasum": "", "shasum": "",
"mirrors": [ "mirrors": [
{ {
@ -686,7 +682,7 @@
"psr/simple-cache": "^1.0", "psr/simple-cache": "^1.0",
"topthink/think-helper": "^3.1" "topthink/think-helper": "^3.1"
}, },
"time": "2020-09-28T08:24:57+00:00", "time": "2021-01-06T12:55:12+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -709,11 +705,7 @@
"keywords": [ "keywords": [
"database", "database",
"orm" "orm"
], ]
"support": {
"issues": "https://github.com/top-think/think-orm/issues",
"source": "https://github.com/top-think/think-orm/tree/v2.0.34"
}
}, },
{ {
"name": "topthink/think-template", "name": "topthink/think-template",

2
vendor/services.php vendored
View File

@ -1,5 +1,5 @@
<?php <?php
// This file is automatically generated at:2021-01-09 18:42:18 // This file is automatically generated at:2021-01-11 11:55:05
declare (strict_types = 1); declare (strict_types = 1);
return array ( return array (
0 => 'think\\admin\\Library', 0 => 'think\\admin\\Library',

View File

@ -19,6 +19,7 @@ services:
before_install: before_install:
- echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- echo 'xdebug.mode = coverage' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
- printf "\n" | pecl install -f redis - printf "\n" | pecl install -f redis
- travis_retry composer self-update - travis_retry composer self-update
- mysql -e 'CREATE DATABASE test;' - mysql -e 'CREATE DATABASE test;'
@ -31,4 +32,4 @@ script:
after_script: after_script:
- travis_retry wget https://scrutinizer-ci.com/ocular.phar - travis_retry wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover build/logs/coverage.xml - php ocular.phar code-coverage:upload --format=php-clover build/logs/coverage.xml

View File

@ -13,7 +13,7 @@ ThinkPHP 6.0
ThinkPHP6.0底层架构采用PHP7.1改写和进一步优化。 ThinkPHP6.0底层架构采用PHP7.1改写和进一步优化。
[官方应用服务市场](https://market.topthink.com) | [`ThinkPHP`开发者扶持计划](https://sites.thinkphp.cn/1782366) [官方应用服务市场](https://market.topthink.com) | [`ThinkAPI`——官方统一API服务](https://docs.topthink.com/think-api/)
## 主要新特性 ## 主要新特性
@ -35,7 +35,7 @@ ThinkPHP6.0底层架构采用PHP7.1改写和进一步优化。
* 统一和精简大量用法 * 统一和精简大量用法
> ThinkPHP6.0的运行环境要求PHP7.1+。 > ThinkPHP6.0的运行环境要求PHP7.1+兼容PHP8.0
## 安装 ## 安装
@ -79,7 +79,7 @@ ThinkPHP遵循Apache2开源协议发布并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。 本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2006-2020 by ThinkPHP (http://thinkphp.cn) All rights reserved。 版权所有Copyright © 2006-2021 by ThinkPHP (http://thinkphp.cn) All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。

View File

@ -39,7 +39,7 @@ use think\initializer\RegisterService;
*/ */
class App extends Container class App extends Container
{ {
const VERSION = '6.0.5'; const VERSION = '6.0.6';
/** /**
* 应用调试模式 * 应用调试模式

View File

@ -380,8 +380,10 @@ class Container implements ContainerInterface, ArrayAccess, IteratorAggregate, C
if ($reflect->hasMethod('__make')) { if ($reflect->hasMethod('__make')) {
$method = $reflect->getMethod('__make'); $method = $reflect->getMethod('__make');
if ($method->isPublic() && $method->isStatic()) { if ($method->isPublic() && $method->isStatic()) {
$args = $this->bindParams($method, $vars); $args = $this->bindParams($method, $vars);
return $method->invokeArgs(null, $args); $object = $method->invokeArgs(null, $args);
$this->invokeAfter($class, $object);
return $object;
} }
} }
@ -440,10 +442,10 @@ class Container implements ContainerInterface, ArrayAccess, IteratorAggregate, C
foreach ($params as $param) { foreach ($params as $param) {
$name = $param->getName(); $name = $param->getName();
$lowerName = Str::snake($name); $lowerName = Str::snake($name);
$class = $param->getClass(); $reflectionType = $param->getType();
if ($class) { if ($reflectionType && $reflectionType->isBuiltin() === false) {
$args[] = $this->getObjectParam($class->getName(), $vars); $args[] = $this->getObjectParam($reflectionType->getName(), $vars);
} elseif (1 == $type && !empty($vars)) { } elseif (1 == $type && !empty($vars)) {
$args[] = array_shift($vars); $args[] = array_shift($vars);
} elseif (0 == $type && array_key_exists($name, $vars)) { } elseif (0 == $type && array_key_exists($name, $vars)) {

View File

@ -1659,7 +1659,7 @@ class Request implements ArrayAccess
$flag = FILTER_FLAG_IPV6; $flag = FILTER_FLAG_IPV6;
break; break;
default: default:
$flag = null; $flag = 0;
break; break;
} }

View File

@ -126,10 +126,10 @@ class Validate
'alpha' => '/^[A-Za-z]+$/', 'alpha' => '/^[A-Za-z]+$/',
'alphaNum' => '/^[A-Za-z0-9]+$/', 'alphaNum' => '/^[A-Za-z0-9]+$/',
'alphaDash' => '/^[A-Za-z0-9\-\_]+$/', 'alphaDash' => '/^[A-Za-z0-9\-\_]+$/',
'chs' => '/^[\x{4e00}-\x{9fa5}]+$/u', 'chs' => '/^[\x{4e00}-\x{9fa5}\x{9fa6}-\x{9fef}\x{3400}-\x{4db5}\x{20000}-\x{2ebe0}]+$/u',
'chsAlpha' => '/^[\x{4e00}-\x{9fa5}a-zA-Z]+$/u', 'chsAlpha' => '/^[\x{4e00}-\x{9fa5}\x{9fa6}-\x{9fef}\x{3400}-\x{4db5}\x{20000}-\x{2ebe0}a-zA-Z]+$/u',
'chsAlphaNum' => '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]+$/u', 'chsAlphaNum' => '/^[\x{4e00}-\x{9fa5}\x{9fa6}-\x{9fef}\x{3400}-\x{4db5}\x{20000}-\x{2ebe0}a-zA-Z0-9]+$/u',
'chsDash' => '/^[\x{4e00}-\x{9fa5}a-zA-Z0-9\_\-]+$/u', 'chsDash' => '/^[\x{4e00}-\x{9fa5}\x{9fa6}-\x{9fef}\x{3400}-\x{4db5}\x{20000}-\x{2ebe0}a-zA-Z0-9\_\-]+$/u',
'mobile' => '/^1[3-9]\d{9}$/', 'mobile' => '/^1[3-9]\d{9}$/',
'idCard' => '/(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$)/', 'idCard' => '/(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}$)/',
'zip' => '/\d{6}/', 'zip' => '/\d{6}/',
@ -1605,6 +1605,11 @@ class Validate
return $this->errorMsgIsArray($msg, $rule, $title); return $this->errorMsgIsArray($msg, $rule, $title);
} }
// rule若是数组则转为字符串
if (is_array($rule)) {
$rule = implode(',', $rule);
}
if (is_scalar($rule) && false !== strpos($msg, ':')) { if (is_scalar($rule) && false !== strpos($msg, ':')) {
// 变量替换 // 变量替换
if (is_string($rule) && strpos($rule, ',')) { if (is_string($rule) && strpos($rule, ',')) {

View File

@ -115,7 +115,11 @@ class View extends Manager
{ {
// 页面缓存 // 页面缓存
ob_start(); ob_start();
ob_implicit_flush(0); if (PHP_VERSION > 8.0) {
ob_implicit_flush(false);
} else {
ob_implicit_flush(0);
}
// 渲染输出 // 渲染输出
try { try {

View File

@ -31,7 +31,10 @@ class VendorPublish extends Command
if (is_file($path = $this->app->getRootPath() . 'vendor/composer/installed.json')) { if (is_file($path = $this->app->getRootPath() . 'vendor/composer/installed.json')) {
$packages = json_decode(@file_get_contents($path), true); $packages = json_decode(@file_get_contents($path), true);
// Compatibility with Composer 2.0
if (isset($packages['packages'])) {
$packages = $packages['packages'];
}
foreach ($packages as $package) { foreach ($packages as $package) {
//配置 //配置
$configDir = $this->app->getConfigPath(); $configDir = $this->app->getConfigPath();

View File

@ -31,6 +31,6 @@ class Middleware extends Make
protected function getNamespace(string $app): string protected function getNamespace(string $app): string
{ {
return 'app\\middleware'; return parent::getNamespace($app) . '\\middleware';
} }
} }

View File

@ -10,6 +10,7 @@
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
namespace think\console\command\optimize; namespace think\console\command\optimize;
use Exception;
use think\console\Command; use think\console\Command;
use think\console\Input; use think\console\Input;
use think\console\input\Argument; use think\console\input\Argument;
@ -78,13 +79,17 @@ class Schema extends Command
{ {
$reflect = new \ReflectionClass($class); $reflect = new \ReflectionClass($class);
if (!$reflect->isAbstract() && $reflect->isSubclassOf('\think\Model')) { if (!$reflect->isAbstract() && $reflect->isSubclassOf('\think\Model')) {
/** @var \think\Model $model */ try {
$model = new $class; /** @var \think\Model $model */
$connection = $model->db()->getConnection(); $model = new $class;
if ($connection instanceof PDOConnection) { $connection = $model->db()->getConnection();
$table = $model->getTable(); if ($connection instanceof PDOConnection) {
//预读字段信息 $table = $model->getTable();
$connection->getSchemaInfo($table, true); //预读字段信息
$connection->getSchemaInfo($table, true);
}
} catch (Exception $e) {
} }
} }
} }

View File

@ -41,6 +41,11 @@ class Socket implements LogHandlerInterface
'expand_level' => ['debug'], 'expand_level' => ['debug'],
// 日志头渲染回调 // 日志头渲染回调
'format_head' => null, 'format_head' => null,
// curl opt
'curl_opt' => [
CURLOPT_CONNECTTIMEOUT => 1,
CURLOPT_TIMEOUT => 10,
],
]; ];
protected $css = [ protected $css = [
@ -292,8 +297,8 @@ class Socket implements LogHandlerInterface
curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $message); curl_setopt($ch, CURLOPT_POSTFIELDS, $message);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->config['curl_opt'][CURLOPT_CONNECTTIMEOUT] ?? 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_TIMEOUT, $this->config['curl_opt'][CURLOPT_TIMEOUT] ?? 10);
$headers = [ $headers = [
"Content-Type: application/json;charset=UTF-8", "Content-Type: application/json;charset=UTF-8",

View File

@ -162,7 +162,7 @@ class CheckRequestCache
foreach ($param as $item => $val) { foreach ($param as $item => $val) {
if (is_string($val) && false !== strpos($key, ':' . $item)) { if (is_string($val) && false !== strpos($key, ':' . $item)) {
$key = str_replace(':' . $item, $val, $key); $key = str_replace(':' . $item, (string) $val, $key);
} }
} }
} elseif (strpos($key, ']')) { } elseif (strpos($key, ']')) {

View File

@ -44,7 +44,9 @@ class File extends Response
throw new Exception('file not exists:' . $data); throw new Exception('file not exists:' . $data);
} }
ob_end_clean(); while (ob_get_level() > 0) {
ob_end_clean();
}
if (!empty($this->name)) { if (!empty($this->name)) {
$name = $this->name; $name = $this->name;

View File

@ -132,7 +132,7 @@ class Resource extends RuleGroup
$ruleItem = $this->addRule(trim($prefix . $val[1], '/'), $this->route . '/' . $val[2], $val[0]); $ruleItem = $this->addRule(trim($prefix . $val[1], '/'), $this->route . '/' . $val[2], $val[0]);
foreach (['model', 'validate', 'middleware'] as $name) { foreach (['model', 'validate', 'middleware', 'pattern'] as $name) {
if (isset($this->$name[$key])) { if (isset($this->$name[$key])) {
call_user_func_array([$ruleItem, $name], (array) $this->$name[$key]); call_user_func_array([$ruleItem, $name], (array) $this->$name[$key]);
} }

View File

@ -806,7 +806,8 @@ abstract class Rule
} }
$regex = str_replace(array_unique($match), array_unique($replace), $rule); $regex = str_replace(array_unique($match), array_unique($replace), $rule);
$regex = str_replace([')?/', ')/', ')?-', ')-', '\\\\/'], [')\/', ')\/', ')\-', ')\-', '\/'], $regex); $regex = str_replace('/', '\/', $regex);
$regex = str_replace([')?\/', ')?-', ')-', '\\\\/'], [')\/', ')\-', ')\-', '\/'], $regex);
if (isset($hasSlash)) { if (isset($hasSlash)) {
$regex .= '\/'; $regex .= '\/';

View File

@ -328,7 +328,7 @@ class Url
foreach ($pattern as $key => $val) { foreach ($pattern as $key => $val) {
if (isset($vars[$key])) { if (isset($vars[$key])) {
$url = str_replace(['[:' . $key . ']', '<' . $key . '?>', ':' . $key, '<' . $key . '>'], $type ? $vars[$key] : urlencode((string) $vars[$key]), $url); $url = str_replace(['[:' . $key . ']', '<' . $key . '?>', ':' . $key, '<' . $key . '>'], $type ? (string) $vars[$key] : urlencode((string) $vars[$key]), $url);
$keys[] = $key; $keys[] = $key;
$url = str_replace(['/?', '-?'], ['/', '-'], $url); $url = str_replace(['/?', '-?'], ['/', '-'], $url);
$result = [rtrim($url, '?/-'), $domain, $suffix]; $result = [rtrim($url, '?/-'), $domain, $suffix];
@ -353,6 +353,11 @@ class Url
return []; return [];
} }
/**
* 生成URL地址
* @access public
* @return string
*/
public function build() public function build()
{ {
// 解析URL // 解析URL

View File

@ -266,6 +266,8 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
*/ */
public function newInstance(array $data = [], $where = null): Model public function newInstance(array $data = [], $where = null): Model
{ {
$this->readDataType($data);
$model = new static($data); $model = new static($data);
if ($this->connection) { if ($this->connection) {
@ -609,9 +611,11 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
return true; return true;
} }
if ($this->autoWriteTimestamp && $this->updateTime && !isset($data[$this->updateTime])) { $this->writeDataType($data);
if ($this->autoWriteTimestamp && $this->updateTime) {
// 自动写入更新时间 // 自动写入更新时间
$data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime); $data[$this->updateTime] = $this->autoWriteTimestamp();
$this->data[$this->updateTime] = $data[$this->updateTime]; $this->data[$this->updateTime] = $data[$this->updateTime];
} }
@ -669,11 +673,11 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
// 时间戳自动写入 // 时间戳自动写入
if ($this->autoWriteTimestamp) { if ($this->autoWriteTimestamp) {
if ($this->createTime && !isset($this->data[$this->createTime])) { if ($this->createTime && !isset($this->data[$this->createTime])) {
$this->data[$this->createTime] = $this->autoWriteTimestamp($this->createTime); $this->data[$this->createTime] = $this->autoWriteTimestamp();
} }
if ($this->updateTime && !isset($this->data[$this->updateTime])) { if ($this->updateTime && !isset($this->data[$this->updateTime])) {
$this->data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime); $this->data[$this->updateTime] = $this->autoWriteTimestamp();
} }
} }
@ -682,6 +686,7 @@ abstract class Model implements JsonSerializable, ArrayAccess, Arrayable, Jsonab
} }
$this->checkData(); $this->checkData();
$this->writeDataType($this->data);
// 检查允许字段 // 检查允许字段
$allowFields = $this->checkAllowFields(); $allowFields = $this->checkAllowFields();

View File

@ -1191,7 +1191,7 @@ abstract class PDOConnection extends Connection
$key = null; $key = null;
} }
if (strpos($column, ',')) { if ('*' == $column || strpos($column, ',')) {
$column = null; $column = null;
} elseif (strpos($column, ' ')) { } elseif (strpos($column, ' ')) {
$column = substr(strrchr(trim($column), ' '), 1); $column = substr(strrchr(trim($column), ' '), 1);
@ -1236,8 +1236,8 @@ abstract class PDOConnection extends Connection
// 判断占位符 // 判断占位符
$sql = is_numeric($key) ? $sql = is_numeric($key) ?
substr_replace($sql, $value, strpos($sql, '?'), 1) : substr_replace($sql, (string) $value, strpos($sql, '?'), 1) :
substr_replace($sql, $value, strpos($sql, ':' . $key), strlen(':' . $key)); substr_replace($sql, (string) $value, strpos($sql, ':' . $key), strlen(':' . $key));
} }
return rtrim($sql); return rtrim($sql);

View File

@ -313,10 +313,15 @@ class Mysql extends Builder
$key = trim($key); $key = trim($key);
if (strpos($key, '->') && false === strpos($key, '(')) { if (strpos($key, '->>') && false === strpos($key, '(')) {
// JSON字段支持
[$field, $name] = explode('->>', $key, 2);
return $this->parseKey($query, $field, true) . '->>\'$' . (strpos($name, '[') === 0 ? '' : '.') . str_replace('->>', '.', $name) . '\'';
} elseif (strpos($key, '->') && false === strpos($key, '(')) {
// JSON字段支持 // JSON字段支持
[$field, $name] = explode('->', $key, 2); [$field, $name] = explode('->', $key, 2);
return 'json_extract(' . $this->parseKey($query, $field) . ', \'$' . (strpos($name, '[') === 0 ? '' : '.') . str_replace('->', '.', $name) . '\')'; return 'json_extract(' . $this->parseKey($query, $field, true) . ', \'$' . (strpos($name, '[') === 0 ? '' : '.') . str_replace('->', '.', $name) . '\')';
} elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) { } elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) {
[$table, $key] = explode('.', $key, 2); [$table, $key] = explode('.', $key, 2);

View File

@ -514,9 +514,17 @@ trait WhereQuery
} }
if ($condition) { if ($condition) {
$this->where($query); if ($query instanceof Closure) {
$query($this, $condition);
} elseif (is_array($query)) {
$this->where($query);
}
} elseif ($otherwise) { } elseif ($otherwise) {
$this->where($otherwise); if ($otherwise instanceof Closure) {
$otherwise($this, $condition);
} elseif (is_array($otherwise)) {
$this->where($otherwise);
}
} }
return $this; return $this;

View File

@ -56,7 +56,7 @@ class Sqlsrv extends PDOConnection
public function getFields(string $tableName): array public function getFields(string $tableName): array
{ {
[$tableName] = explode(' ', $tableName); [$tableName] = explode(' ', $tableName);
strpos($tableName,'.') && $tableName = substr($tableName,strpos($tableName,'.') + 1);
$sql = "SELECT column_name, data_type, column_default, is_nullable $sql = "SELECT column_name, data_type, column_default, is_nullable
FROM information_schema.tables AS t FROM information_schema.tables AS t
JOIN information_schema.columns AS c JOIN information_schema.columns AS c

View File

@ -28,14 +28,17 @@ class PDOException extends DbException
*/ */
public function __construct(\PDOException $exception, array $config = [], string $sql = '', int $code = 10501) public function __construct(\PDOException $exception, array $config = [], string $sql = '', int $code = 10501)
{ {
$error = $exception->errorInfo; $error = $exception->errorInfo;
$message = $exception->getMessage();
$this->setData('PDO Error Info', [ if (!empty($error)) {
'SQLSTATE' => $error[0], $this->setData('PDO Error Info', [
'Driver Error Code' => isset($error[1]) ? $error[1] : 0, 'SQLSTATE' => $error[0],
'Driver Error Message' => isset($error[2]) ? $error[2] : '', 'Driver Error Code' => isset($error[1]) ? $error[1] : 0,
]); 'Driver Error Message' => isset($error[2]) ? $error[2] : '',
]);
}
parent::__construct($exception->getMessage(), $config, $sql, $code); parent::__construct($message, $config, $sql, $code);
} }
} }

View File

@ -358,25 +358,17 @@ trait Attribute
return; return;
} }
if (is_null($value) && $this->autoWriteTimestamp && in_array($name, [$this->createTime, $this->updateTime])) { // 检测修改器
// 自动写入的时间戳字段 $method = 'set' . Str::studly($name) . 'Attr';
$value = $this->autoWriteTimestamp();
} else {
// 检测修改器
$method = 'set' . Str::studly($name) . 'Attr';
if (method_exists($this, $method)) { if (method_exists($this, $method)) {
$array = $this->data; $array = $this->data;
$value = $this->$method($value, array_merge($this->data, $data)); $value = $this->$method($value, array_merge($this->data, $data));
$this->set[$name] = true; $this->set[$name] = true;
if (is_null($value) && $array !== $this->data) { if (is_null($value) && $array !== $this->data) {
return; return;
}
} elseif (isset($this->type[$name])) {
// 类型转换
$value = $this->writeTransform($value, $this->type[$name]);
} }
} }
@ -506,11 +498,6 @@ trait Attribute
} }
$value = $this->$method($value, $this->data); $value = $this->$method($value, $this->data);
} elseif (isset($this->type[$fieldName])) {
// 类型转换
$value = $this->readTransform($value, $this->type[$fieldName]);
} elseif ($this->autoWriteTimestamp && in_array($fieldName, [$this->createTime, $this->updateTime])) {
$value = $this->getTimestampValue($value);
} elseif ($relation) { } elseif ($relation) {
$value = $this->getRelationValue($relation); $value = $this->getRelationValue($relation);
// 保存关联对象值 // 保存关联对象值
@ -520,6 +507,43 @@ trait Attribute
return $value; return $value;
} }
/**
* 读取数据类型处理
* @access protected
* @param array $data 数据
* @return void
*/
protected function readDataType(array &$data): void
{
foreach ($data as $name => &$value) {
if (isset($this->type[$name])) {
// 类型转换
$value = $this->readTransform($value, $this->type[$name]);
} elseif ($this->autoWriteTimestamp && in_array($name, [$this->createTime, $this->updateTime])) {
$value = $this->getTimestampValue($value);
}
}
}
/**
* 写入数据类型处理
* @access protected
* @param array $data 数据
* @return void
*/
protected function writeDataType(array &$data): void
{
foreach ($data as $name => &$value) {
if (isset($this->type[$name])) {
// 类型转换
$value = $this->writeTransform($value, $this->type[$name]);
} elseif (is_null($value) && $this->autoWriteTimestamp && in_array($name, [$this->createTime, $this->updateTime])) {
// 自动写入的时间戳字段
$value = $this->autoWriteTimestamp();
}
}
}
/** /**
* 获取JSON字段属性值 * 获取JSON字段属性值
* @access protected * @access protected

View File

@ -42,6 +42,12 @@ trait Conversion
*/ */
protected $append = []; protected $append = [];
/**
* 数据输出字段映射
* @var array
*/
protected $mapping = [];
/** /**
* 数据集对象名 * 数据集对象名
* @var string * @var string
@ -137,6 +143,19 @@ trait Conversion
return $this; return $this;
} }
/**
* 设置属性的映射输出
* @access public
* @param array $map
* @return $this
*/
public function mapping(array $map)
{
$this->mapping = $map;
return $this;
}
/** /**
* 转换当前模型对象为数组 * 转换当前模型对象为数组
* @access public * @access public
@ -192,6 +211,13 @@ trait Conversion
} elseif (!isset($this->hidden[$key]) && !$hasVisible) { } elseif (!isset($this->hidden[$key]) && !$hasVisible) {
$item[$key] = $this->getAttr($key); $item[$key] = $this->getAttr($key);
} }
if (isset($this->mapping[$key])) {
// 检查字段映射
$mapName = $this->mapping[$key];
$item[$mapName] = $item[$key];
unset($item[$key]);
}
} }
// 追加属性(必须定义获取器) // 追加属性(必须定义获取器)