mirror of https://github.com/1099438829/apeblog
更新vendor和首台首页
This commit is contained in:
parent
ecdf50d355
commit
3b715806fd
|
|
@ -51,6 +51,12 @@ class Index extends AuthController
|
||||||
$this->assign("friend_link_count", $FriendLinkCount);
|
$this->assign("friend_link_count", $FriendLinkCount);
|
||||||
$messageFormCount = MessageForm::counts(new MessageForm());
|
$messageFormCount = MessageForm::counts(new MessageForm());
|
||||||
$this->assign("message_form_count", $messageFormCount);
|
$this->assign("message_form_count", $messageFormCount);
|
||||||
|
$data =[
|
||||||
|
"page"=> 0 ,
|
||||||
|
"limit" => 5
|
||||||
|
];
|
||||||
|
$articleList = Document::systemPage($data)['data'];
|
||||||
|
$this->assign("article_list", $articleList);
|
||||||
return $this->fetch();
|
return $this->fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,40 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>项目信息</h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>文章标题</th>
|
||||||
|
<th>文章分类</th>
|
||||||
|
<th>发布时间</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{volist name="article_list" id="vo"}
|
||||||
|
<tr>
|
||||||
|
<td>{$vo.id}</td>
|
||||||
|
<td>{$vo.title}</td>
|
||||||
|
<td>{$vo.category_title}</td>
|
||||||
|
<td>{$vo.create_time}</td>
|
||||||
|
</tr>
|
||||||
|
{/volist}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/admin/js/jquery.min.js"></script>
|
<script type="text/javascript" src="/static/admin/js/jquery.min.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,10 @@ class Document extends BaseModel
|
||||||
{
|
{
|
||||||
$model = new self;
|
$model = new self;
|
||||||
$model = $model->where("type", "=", $where['type'] ?? Data::DOCUMENT_TYPE_ARTICLE);
|
$model = $model->where("type", "=", $where['type'] ?? Data::DOCUMENT_TYPE_ARTICLE);
|
||||||
if ($where['title'] != '') $model = $model->where("title", "like", "%$where[title]%");
|
if (!empty($where['title'])) $model = $model->where("title", "like", "%$where[title]%");
|
||||||
if ($where['start_time'] != '') $model = $model->where("create_time", ">", strtotime($where['start_time'] . " 00:00:00"));
|
if (!empty($where['start_time'])) $model = $model->where("create_time", ">", strtotime($where['start_time'] . " 00:00:00"));
|
||||||
if ($where['end_time'] != '') $model = $model->where("create_time", "<", strtotime($where['end_time'] . " 23:59:59"));
|
if (!empty($where['end_time'])) $model = $model->where("create_time", "<", strtotime($where['end_time'] . " 23:59:59"));
|
||||||
if ($where['status'] != '') $model = $model->where("status", $where['status']);
|
if (!empty($where['status'])) $model = $model->where("status", $where['status']);
|
||||||
$model = $model->order("sort desc")->order("id desc");
|
$model = $model->order("sort desc")->order("id desc");
|
||||||
$count = self::counts($model);
|
$count = self::counts($model);
|
||||||
if ($where['page'] && $where['limit']) $model = $model->page((int)$where['page'], (int)$where['limit']);
|
if ($where['page'] && $where['limit']) $model = $model->page((int)$where['page'], (int)$where['limit']);
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,10 @@ if (PHP_VERSION_ID < 80000) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) {
|
if (
|
||||||
|
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||||
|
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||||
|
) {
|
||||||
include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server');
|
include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server');
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
setlocal DISABLEDELAYEDEXPANSION
|
setlocal DISABLEDELAYEDEXPANSION
|
||||||
SET BIN_TARGET=%~dp0/var-dump-server
|
SET BIN_TARGET=%~dp0/var-dump-server
|
||||||
SET COMPOSER_BIN_DIR=%~dp0
|
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
|
||||||
php "%BIN_TARGET%" %*
|
php "%BIN_TARGET%" %*
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ return array(
|
||||||
'think\\view\\driver\\' => array($vendorDir . '/topthink/think-view/src'),
|
'think\\view\\driver\\' => array($vendorDir . '/topthink/think-view/src'),
|
||||||
'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
|
'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
|
||||||
'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'),
|
'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'),
|
||||||
'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/think-orm/src'),
|
'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src'),
|
||||||
'app\\' => array($baseDir . '/app'),
|
'app\\' => array($baseDir . '/app'),
|
||||||
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
||||||
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
|
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@ class ComposerStaticInit4b57298e8d0e895486f3307a354a7e1a
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/topthink/framework/src/think',
|
0 => __DIR__ . '/..' . '/topthink/framework/src/think',
|
||||||
1 => __DIR__ . '/..' . '/topthink/think-helper/src',
|
1 => __DIR__ . '/..' . '/topthink/think-helper/src',
|
||||||
2 => __DIR__ . '/..' . '/topthink/think-template/src',
|
2 => __DIR__ . '/..' . '/topthink/think-orm/src',
|
||||||
3 => __DIR__ . '/..' . '/topthink/think-orm/src',
|
3 => __DIR__ . '/..' . '/topthink/think-template/src',
|
||||||
),
|
),
|
||||||
'app\\' =>
|
'app\\' =>
|
||||||
array (
|
array (
|
||||||
|
|
|
||||||
|
|
@ -915,17 +915,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/http-foundation",
|
"name": "symfony/http-foundation",
|
||||||
"version": "v5.4.10",
|
"version": "v5.4.12",
|
||||||
"version_normalized": "5.4.10.0",
|
"version_normalized": "5.4.12.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/http-foundation.git",
|
"url": "https://github.com/symfony/http-foundation.git",
|
||||||
"reference": "e7793b7906f72a8cc51054fbca9dcff7a8af1c1e"
|
"reference": "f4bfe9611b113b15d98a43da68ec9b5a00d56791"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/e7793b7906f72a8cc51054fbca9dcff7a8af1c1e",
|
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/f4bfe9611b113b15d98a43da68ec9b5a00d56791",
|
||||||
"reference": "e7793b7906f72a8cc51054fbca9dcff7a8af1c1e",
|
"reference": "f4bfe9611b113b15d98a43da68ec9b5a00d56791",
|
||||||
"shasum": "",
|
"shasum": "",
|
||||||
"mirrors": [
|
"mirrors": [
|
||||||
{
|
{
|
||||||
|
|
@ -943,13 +943,16 @@
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"predis/predis": "~1.0",
|
"predis/predis": "~1.0",
|
||||||
"symfony/cache": "^4.4|^5.0|^6.0",
|
"symfony/cache": "^4.4|^5.0|^6.0",
|
||||||
|
"symfony/dependency-injection": "^5.4|^6.0",
|
||||||
"symfony/expression-language": "^4.4|^5.0|^6.0",
|
"symfony/expression-language": "^4.4|^5.0|^6.0",
|
||||||
"symfony/mime": "^4.4|^5.0|^6.0"
|
"symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4",
|
||||||
|
"symfony/mime": "^4.4|^5.0|^6.0",
|
||||||
|
"symfony/rate-limiter": "^5.2|^6.0"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"symfony/mime": "To use the file extension guesser"
|
"symfony/mime": "To use the file extension guesser"
|
||||||
},
|
},
|
||||||
"time": "2022-06-19T13:13:40+00:00",
|
"time": "2022-08-19T07:33:17+00:00",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -977,7 +980,7 @@
|
||||||
"description": "Defines an object-oriented layer for the HTTP specification",
|
"description": "Defines an object-oriented layer for the HTTP specification",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/http-foundation/tree/v5.4.10"
|
"source": "https://github.com/symfony/http-foundation/tree/v5.4.12"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -1266,17 +1269,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-dumper",
|
"name": "symfony/var-dumper",
|
||||||
"version": "v4.4.42",
|
"version": "v4.4.44",
|
||||||
"version_normalized": "4.4.42.0",
|
"version_normalized": "4.4.44.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/var-dumper.git",
|
"url": "https://github.com/symfony/var-dumper.git",
|
||||||
"reference": "742aab50ad097bcb62d91fccb613f66b8047d2ca"
|
"reference": "f19951007dae942cc79b979c1fe26bfdfbeb54ed"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/742aab50ad097bcb62d91fccb613f66b8047d2ca",
|
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/f19951007dae942cc79b979c1fe26bfdfbeb54ed",
|
||||||
"reference": "742aab50ad097bcb62d91fccb613f66b8047d2ca",
|
"reference": "f19951007dae942cc79b979c1fe26bfdfbeb54ed",
|
||||||
"shasum": "",
|
"shasum": "",
|
||||||
"mirrors": [
|
"mirrors": [
|
||||||
{
|
{
|
||||||
|
|
@ -1306,7 +1309,7 @@
|
||||||
"ext-intl": "To show region name in time zone dump",
|
"ext-intl": "To show region name in time zone dump",
|
||||||
"symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
|
"symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
|
||||||
},
|
},
|
||||||
"time": "2022-05-21T10:00:54+00:00",
|
"time": "2022-07-20T09:59:04+00:00",
|
||||||
"bin": [
|
"bin": [
|
||||||
"Resources/bin/var-dump-server"
|
"Resources/bin/var-dump-server"
|
||||||
],
|
],
|
||||||
|
|
@ -1344,7 +1347,7 @@
|
||||||
"dump"
|
"dump"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/var-dumper/tree/v4.4.42"
|
"source": "https://github.com/symfony/var-dumper/tree/v4.4.44"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|
@ -1364,17 +1367,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "topthink/framework",
|
"name": "topthink/framework",
|
||||||
"version": "v6.0.12",
|
"version": "v6.0.13",
|
||||||
"version_normalized": "6.0.12.0",
|
"version_normalized": "6.0.13.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/top-think/framework.git",
|
"url": "https://github.com/top-think/framework.git",
|
||||||
"reference": "e478316ac843c1a884a3b3a7a94db17c4001ff5c"
|
"reference": "126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/top-think/framework/zipball/e478316ac843c1a884a3b3a7a94db17c4001ff5c",
|
"url": "https://api.github.com/repos/top-think/framework/zipball/126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6",
|
||||||
"reference": "e478316ac843c1a884a3b3a7a94db17c4001ff5c",
|
"reference": "126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6",
|
||||||
"shasum": "",
|
"shasum": "",
|
||||||
"mirrors": [
|
"mirrors": [
|
||||||
{
|
{
|
||||||
|
|
@ -1402,7 +1405,7 @@
|
||||||
"mockery/mockery": "^1.2",
|
"mockery/mockery": "^1.2",
|
||||||
"phpunit/phpunit": "^7.0"
|
"phpunit/phpunit": "^7.0"
|
||||||
},
|
},
|
||||||
"time": "2022-01-21T06:31:07+00:00",
|
"time": "2022-07-15T02:52:08+00:00",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -1434,7 +1437,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/top-think/framework/issues",
|
"issues": "https://github.com/top-think/framework/issues",
|
||||||
"source": "https://github.com/top-think/framework/tree/v6.0.12"
|
"source": "https://github.com/top-think/framework/tree/v6.0.13"
|
||||||
},
|
},
|
||||||
"install-path": "../topthink/framework"
|
"install-path": "../topthink/framework"
|
||||||
},
|
},
|
||||||
|
|
@ -1614,17 +1617,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "topthink/think-orm",
|
"name": "topthink/think-orm",
|
||||||
"version": "v2.0.53",
|
"version": "v2.0.54",
|
||||||
"version_normalized": "2.0.53.0",
|
"version_normalized": "2.0.54.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": "06783eda65547a70ea686360a897759e1f873fff"
|
"reference": "97b061b47616301ff29fbd4c35ed9184e1162e4e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/top-think/think-orm/zipball/06783eda65547a70ea686360a897759e1f873fff",
|
"url": "https://api.github.com/repos/top-think/think-orm/zipball/97b061b47616301ff29fbd4c35ed9184e1162e4e",
|
||||||
"reference": "06783eda65547a70ea686360a897759e1f873fff",
|
"reference": "97b061b47616301ff29fbd4c35ed9184e1162e4e",
|
||||||
"shasum": "",
|
"shasum": "",
|
||||||
"mirrors": [
|
"mirrors": [
|
||||||
{
|
{
|
||||||
|
|
@ -1637,14 +1640,14 @@
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
"php": ">=7.1.0",
|
"php": ">=7.1.0",
|
||||||
"psr/log": "~1.0",
|
"psr/log": "^1.0|^2.0",
|
||||||
"psr/simple-cache": "^1.0",
|
"psr/simple-cache": "^1.0|^2.0",
|
||||||
"topthink/think-helper": "^3.1"
|
"topthink/think-helper": "^3.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^7|^8|^9.5"
|
"phpunit/phpunit": "^7|^8|^9.5"
|
||||||
},
|
},
|
||||||
"time": "2022-02-28T14:54:22+00:00",
|
"time": "2022-07-05T05:25:51+00:00",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
@ -1672,7 +1675,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/top-think/think-orm/issues",
|
"issues": "https://github.com/top-think/think-orm/issues",
|
||||||
"source": "https://github.com/top-think/think-orm/tree/v2.0.53"
|
"source": "https://github.com/top-think/think-orm/tree/v2.0.54"
|
||||||
},
|
},
|
||||||
"install-path": "../topthink/think-orm"
|
"install-path": "../topthink/think-orm"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
'name' => 'topthink/think',
|
'name' => 'topthink/think',
|
||||||
'pretty_version' => 'dev-master',
|
'pretty_version' => 'dev-master',
|
||||||
'version' => 'dev-master',
|
'version' => 'dev-master',
|
||||||
'reference' => 'dc0fcfd1eb5f19c42b2ec51208d3bca840538c92',
|
'reference' => 'ecdf50d35553ba71e48f82e41d38feb090fd0f7b',
|
||||||
'type' => 'project',
|
'type' => 'project',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
|
|
@ -128,9 +128,9 @@
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'symfony/http-foundation' => array(
|
'symfony/http-foundation' => array(
|
||||||
'pretty_version' => 'v5.4.10',
|
'pretty_version' => 'v5.4.12',
|
||||||
'version' => '5.4.10.0',
|
'version' => '5.4.12.0',
|
||||||
'reference' => 'e7793b7906f72a8cc51054fbca9dcff7a8af1c1e',
|
'reference' => 'f4bfe9611b113b15d98a43da68ec9b5a00d56791',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../symfony/http-foundation',
|
'install_path' => __DIR__ . '/../symfony/http-foundation',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
|
|
@ -164,18 +164,18 @@
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'symfony/var-dumper' => array(
|
'symfony/var-dumper' => array(
|
||||||
'pretty_version' => 'v4.4.42',
|
'pretty_version' => 'v4.4.44',
|
||||||
'version' => '4.4.42.0',
|
'version' => '4.4.44.0',
|
||||||
'reference' => '742aab50ad097bcb62d91fccb613f66b8047d2ca',
|
'reference' => 'f19951007dae942cc79b979c1fe26bfdfbeb54ed',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../symfony/var-dumper',
|
'install_path' => __DIR__ . '/../symfony/var-dumper',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
'dev_requirement' => true,
|
'dev_requirement' => true,
|
||||||
),
|
),
|
||||||
'topthink/framework' => array(
|
'topthink/framework' => array(
|
||||||
'pretty_version' => 'v6.0.12',
|
'pretty_version' => 'v6.0.13',
|
||||||
'version' => '6.0.12.0',
|
'version' => '6.0.13.0',
|
||||||
'reference' => 'e478316ac843c1a884a3b3a7a94db17c4001ff5c',
|
'reference' => '126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../topthink/framework',
|
'install_path' => __DIR__ . '/../topthink/framework',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
|
|
@ -184,7 +184,7 @@
|
||||||
'topthink/think' => array(
|
'topthink/think' => array(
|
||||||
'pretty_version' => 'dev-master',
|
'pretty_version' => 'dev-master',
|
||||||
'version' => 'dev-master',
|
'version' => 'dev-master',
|
||||||
'reference' => 'dc0fcfd1eb5f19c42b2ec51208d3bca840538c92',
|
'reference' => 'ecdf50d35553ba71e48f82e41d38feb090fd0f7b',
|
||||||
'type' => 'project',
|
'type' => 'project',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
|
|
@ -218,9 +218,9 @@
|
||||||
'dev_requirement' => false,
|
'dev_requirement' => false,
|
||||||
),
|
),
|
||||||
'topthink/think-orm' => array(
|
'topthink/think-orm' => array(
|
||||||
'pretty_version' => 'v2.0.53',
|
'pretty_version' => 'v2.0.54',
|
||||||
'version' => '2.0.53.0',
|
'version' => '2.0.54.0',
|
||||||
'reference' => '06783eda65547a70ea686360a897759e1f873fff',
|
'reference' => '97b061b47616301ff29fbd4c35ed9184e1162e4e',
|
||||||
'type' => 'library',
|
'type' => 'library',
|
||||||
'install_path' => __DIR__ . '/../topthink/think-orm',
|
'install_path' => __DIR__ . '/../topthink/think-orm',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
// This file is automatically generated at:2022-07-10 21:24:02
|
// This file is automatically generated at:2022-08-28 11:10:37
|
||||||
declare (strict_types = 1);
|
declare (strict_types = 1);
|
||||||
return array (
|
return array (
|
||||||
0 => 'think\\captcha\\CaptchaService',
|
0 => 'think\\captcha\\CaptchaService',
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ class BinaryFileResponse extends Response
|
||||||
protected $offset = 0;
|
protected $offset = 0;
|
||||||
protected $maxlen = -1;
|
protected $maxlen = -1;
|
||||||
protected $deleteFileAfterSend = false;
|
protected $deleteFileAfterSend = false;
|
||||||
|
protected $chunkSize = 8 * 1024;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \SplFileInfo|string $file The file to stream
|
* @param \SplFileInfo|string $file The file to stream
|
||||||
|
|
@ -125,6 +126,22 @@ class BinaryFileResponse extends Response
|
||||||
return $this->file;
|
return $this->file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the response stream chunk size.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setChunkSize(int $chunkSize): self
|
||||||
|
{
|
||||||
|
if ($chunkSize < 1 || $chunkSize > \PHP_INT_MAX) {
|
||||||
|
throw new \LogicException('The chunk size of a BinaryFileResponse cannot be less than 1 or greater than PHP_INT_MAX.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->chunkSize = $chunkSize;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Automatically sets the Last-Modified header according the file modification date.
|
* Automatically sets the Last-Modified header according the file modification date.
|
||||||
*
|
*
|
||||||
|
|
@ -306,7 +323,23 @@ class BinaryFileResponse extends Response
|
||||||
$out = fopen('php://output', 'w');
|
$out = fopen('php://output', 'w');
|
||||||
$file = fopen($this->file->getPathname(), 'r');
|
$file = fopen($this->file->getPathname(), 'r');
|
||||||
|
|
||||||
stream_copy_to_stream($file, $out, $this->maxlen, $this->offset);
|
ignore_user_abort(true);
|
||||||
|
|
||||||
|
if (0 !== $this->offset) {
|
||||||
|
fseek($file, $this->offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = $this->maxlen;
|
||||||
|
while ($length && !feof($file)) {
|
||||||
|
$read = ($length > $this->chunkSize) ? $this->chunkSize : $length;
|
||||||
|
$length -= $read;
|
||||||
|
|
||||||
|
stream_copy_to_stream($file, $out, $read);
|
||||||
|
|
||||||
|
if (connection_aborted()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fclose($out);
|
fclose($out);
|
||||||
fclose($file);
|
fclose($file);
|
||||||
|
|
|
||||||
|
|
@ -223,8 +223,8 @@ class UploadedFile extends File
|
||||||
*/
|
*/
|
||||||
public static function getMaxFilesize()
|
public static function getMaxFilesize()
|
||||||
{
|
{
|
||||||
$sizePostMax = self::parseFilesize(ini_get('post_max_size'));
|
$sizePostMax = self::parseFilesize(\ini_get('post_max_size'));
|
||||||
$sizeUploadMax = self::parseFilesize(ini_get('upload_max_filesize'));
|
$sizeUploadMax = self::parseFilesize(\ini_get('upload_max_filesize'));
|
||||||
|
|
||||||
return min($sizePostMax ?: \PHP_INT_MAX, $sizeUploadMax ?: \PHP_INT_MAX);
|
return min($sizePostMax ?: \PHP_INT_MAX, $sizeUploadMax ?: \PHP_INT_MAX);
|
||||||
}
|
}
|
||||||
|
|
@ -253,8 +253,11 @@ class UploadedFile extends File
|
||||||
|
|
||||||
switch (substr($size, -1)) {
|
switch (substr($size, -1)) {
|
||||||
case 't': $max *= 1024;
|
case 't': $max *= 1024;
|
||||||
|
// no break
|
||||||
case 'g': $max *= 1024;
|
case 'g': $max *= 1024;
|
||||||
|
// no break
|
||||||
case 'm': $max *= 1024;
|
case 'm': $max *= 1024;
|
||||||
|
// no break
|
||||||
case 'k': $max *= 1024;
|
case 'k': $max *= 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,14 @@ final class InputBag extends ParameterBag
|
||||||
*/
|
*/
|
||||||
public function get(string $key, $default = null)
|
public function get(string $key, $default = null)
|
||||||
{
|
{
|
||||||
if (null !== $default && !is_scalar($default) && !(\is_object($default) && method_exists($default, '__toString'))) {
|
if (null !== $default && !\is_scalar($default) && !(\is_object($default) && method_exists($default, '__toString'))) {
|
||||||
trigger_deprecation('symfony/http-foundation', '5.1', 'Passing a non-scalar value as 2nd argument to "%s()" is deprecated, pass a scalar or null instead.', __METHOD__);
|
trigger_deprecation('symfony/http-foundation', '5.1', 'Passing a non-scalar value as 2nd argument to "%s()" is deprecated, pass a scalar or null instead.', __METHOD__);
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = parent::get($key, $this);
|
$value = parent::get($key, $this);
|
||||||
|
|
||||||
if (null !== $value && $this !== $value && !is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
|
if (null !== $value && $this !== $value && !\is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
|
||||||
trigger_deprecation('symfony/http-foundation', '5.1', 'Retrieving a non-string value from "%s()" is deprecated, and will throw a "%s" exception in Symfony 6.0, use "%s::all($key)" instead.', __METHOD__, BadRequestException::class, __CLASS__);
|
trigger_deprecation('symfony/http-foundation', '5.1', 'Retrieving a non-scalar value from "%s()" is deprecated, and will throw a "%s" exception in Symfony 6.0, use "%s::all($key)" instead.', __METHOD__, BadRequestException::class, __CLASS__);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this === $value ? $default : $value;
|
return $this === $value ? $default : $value;
|
||||||
|
|
@ -76,7 +76,7 @@ final class InputBag extends ParameterBag
|
||||||
*/
|
*/
|
||||||
public function set(string $key, $value)
|
public function set(string $key, $value)
|
||||||
{
|
{
|
||||||
if (null !== $value && !is_scalar($value) && !\is_array($value) && !method_exists($value, '__toString')) {
|
if (null !== $value && !\is_scalar($value) && !\is_array($value) && !method_exists($value, '__toString')) {
|
||||||
trigger_deprecation('symfony/http-foundation', '5.1', 'Passing "%s" as a 2nd Argument to "%s()" is deprecated, pass a scalar, array, or null instead.', get_debug_type($value), __METHOD__);
|
trigger_deprecation('symfony/http-foundation', '5.1', 'Passing "%s" as a 2nd Argument to "%s()" is deprecated, pass a scalar, array, or null instead.', get_debug_type($value), __METHOD__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ class ParameterBag implements \IteratorAggregate, \Countable
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function all(/*string $key = null*/)
|
public function all(/* string $key = null */)
|
||||||
{
|
{
|
||||||
$key = \func_num_args() > 0 ? func_get_arg(0) : null;
|
$key = \func_num_args() > 0 ? func_get_arg(0) : null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,7 @@ abstract class AbstractRequestRateLimiter implements RequestRateLimiterInterface
|
||||||
foreach ($limiters as $limiter) {
|
foreach ($limiters as $limiter) {
|
||||||
$rateLimit = $limiter->consume(1);
|
$rateLimit = $limiter->consume(1);
|
||||||
|
|
||||||
if (null === $minimalRateLimit || $rateLimit->getRemainingTokens() < $minimalRateLimit->getRemainingTokens()) {
|
$minimalRateLimit = $minimalRateLimit ? self::getMinimalRateLimit($minimalRateLimit, $rateLimit) : $rateLimit;
|
||||||
$minimalRateLimit = $rateLimit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $minimalRateLimit;
|
return $minimalRateLimit;
|
||||||
|
|
@ -54,4 +52,20 @@ abstract class AbstractRequestRateLimiter implements RequestRateLimiterInterface
|
||||||
* @return LimiterInterface[] a set of limiters using keys extracted from the request
|
* @return LimiterInterface[] a set of limiters using keys extracted from the request
|
||||||
*/
|
*/
|
||||||
abstract protected function getLimiters(Request $request): array;
|
abstract protected function getLimiters(Request $request): array;
|
||||||
|
|
||||||
|
private static function getMinimalRateLimit(RateLimit $first, RateLimit $second): RateLimit
|
||||||
|
{
|
||||||
|
if ($first->isAccepted() !== $second->isAccepted()) {
|
||||||
|
return $first->isAccepted() ? $second : $first;
|
||||||
|
}
|
||||||
|
|
||||||
|
$firstRemainingTokens = $first->getRemainingTokens();
|
||||||
|
$secondRemainingTokens = $second->getRemainingTokens();
|
||||||
|
|
||||||
|
if ($firstRemainingTokens === $secondRemainingTokens) {
|
||||||
|
return $first->getRetryAfter() < $second->getRetryAfter() ? $second : $first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $firstRemainingTokens > $secondRemainingTokens ? $second : $first;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -562,7 +562,7 @@ class Request
|
||||||
|
|
||||||
$request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE];
|
$request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE];
|
||||||
|
|
||||||
$requestOrder = ini_get('request_order') ?: ini_get('variables_order');
|
$requestOrder = \ini_get('request_order') ?: \ini_get('variables_order');
|
||||||
$requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp';
|
$requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp';
|
||||||
|
|
||||||
$_REQUEST = [[]];
|
$_REQUEST = [[]];
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ class Response
|
||||||
public const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585
|
public const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585
|
||||||
public const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585
|
public const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585
|
||||||
public const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585
|
public const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585
|
||||||
public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451;
|
public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; // RFC7725
|
||||||
public const HTTP_INTERNAL_SERVER_ERROR = 500;
|
public const HTTP_INTERNAL_SERVER_ERROR = 500;
|
||||||
public const HTTP_NOT_IMPLEMENTED = 501;
|
public const HTTP_NOT_IMPLEMENTED = 501;
|
||||||
public const HTTP_BAD_GATEWAY = 502;
|
public const HTTP_BAD_GATEWAY = 502;
|
||||||
|
|
@ -1245,6 +1245,7 @@ class Response
|
||||||
while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) {
|
while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) {
|
||||||
if ($flush) {
|
if ($flush) {
|
||||||
ob_end_flush();
|
ob_end_flush();
|
||||||
|
flush();
|
||||||
} else {
|
} else {
|
||||||
ob_end_clean();
|
ob_end_clean();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess
|
||||||
public function open($savePath, $sessionName)
|
public function open($savePath, $sessionName)
|
||||||
{
|
{
|
||||||
$this->sessionName = $sessionName;
|
$this->sessionName = $sessionName;
|
||||||
if (!headers_sent() && !ini_get('session.cache_limiter') && '0' !== ini_get('session.cache_limiter')) {
|
if (!headers_sent() && !\ini_get('session.cache_limiter') && '0' !== \ini_get('session.cache_limiter')) {
|
||||||
header(sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) ini_get('session.cache_expire')));
|
header(sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) \ini_get('session.cache_expire')));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -126,7 +126,7 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess
|
||||||
#[\ReturnTypeWillChange]
|
#[\ReturnTypeWillChange]
|
||||||
public function destroy($sessionId)
|
public function destroy($sessionId)
|
||||||
{
|
{
|
||||||
if (!headers_sent() && filter_var(ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN)) {
|
if (!headers_sent() && filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN)) {
|
||||||
if (!$this->sessionName) {
|
if (!$this->sessionName) {
|
||||||
throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class));
|
throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class));
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +141,7 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess
|
||||||
*/
|
*/
|
||||||
if (null === $cookie || isset($_COOKIE[$this->sessionName])) {
|
if (null === $cookie || isset($_COOKIE[$this->sessionName])) {
|
||||||
if (\PHP_VERSION_ID < 70300) {
|
if (\PHP_VERSION_ID < 70300) {
|
||||||
setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), filter_var(ini_get('session.cookie_secure'), \FILTER_VALIDATE_BOOLEAN), filter_var(ini_get('session.cookie_httponly'), \FILTER_VALIDATE_BOOLEAN));
|
setcookie($this->sessionName, '', 0, \ini_get('session.cookie_path'), \ini_get('session.cookie_domain'), filter_var(\ini_get('session.cookie_secure'), \FILTER_VALIDATE_BOOLEAN), filter_var(\ini_get('session.cookie_httponly'), \FILTER_VALIDATE_BOOLEAN));
|
||||||
} else {
|
} else {
|
||||||
$params = session_get_cookie_params();
|
$params = session_get_cookie_params();
|
||||||
unset($params['lifetime']);
|
unset($params['lifetime']);
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler
|
||||||
#[\ReturnTypeWillChange]
|
#[\ReturnTypeWillChange]
|
||||||
public function updateTimestamp($sessionId, $data)
|
public function updateTimestamp($sessionId, $data)
|
||||||
{
|
{
|
||||||
$this->memcached->touch($this->prefix.$sessionId, time() + (int) ($this->ttl ?? ini_get('session.gc_maxlifetime')));
|
$this->memcached->touch($this->prefix.$sessionId, time() + (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +87,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler
|
||||||
*/
|
*/
|
||||||
protected function doWrite(string $sessionId, string $data)
|
protected function doWrite(string $sessionId, string $data)
|
||||||
{
|
{
|
||||||
return $this->memcached->set($this->prefix.$sessionId, $data, time() + (int) ($this->ttl ?? ini_get('session.gc_maxlifetime')));
|
return $this->memcached->set($this->prefix.$sessionId, $data, time() + (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler
|
||||||
*/
|
*/
|
||||||
protected function doWrite(string $sessionId, string $data)
|
protected function doWrite(string $sessionId, string $data)
|
||||||
{
|
{
|
||||||
$expiry = new UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000);
|
$expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000);
|
||||||
|
|
||||||
$fields = [
|
$fields = [
|
||||||
$this->options['time_field'] => new UTCDateTime(),
|
$this->options['time_field'] => new UTCDateTime(),
|
||||||
|
|
@ -144,7 +144,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler
|
||||||
#[\ReturnTypeWillChange]
|
#[\ReturnTypeWillChange]
|
||||||
public function updateTimestamp($sessionId, $data)
|
public function updateTimestamp($sessionId, $data)
|
||||||
{
|
{
|
||||||
$expiry = new UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000);
|
$expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000);
|
||||||
|
|
||||||
$this->getCollection()->updateOne(
|
$this->getCollection()->updateOne(
|
||||||
[$this->options['id_field'] => $sessionId],
|
[$this->options['id_field'] => $sessionId],
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ class NativeFileSessionHandler extends \SessionHandler
|
||||||
public function __construct(string $savePath = null)
|
public function __construct(string $savePath = null)
|
||||||
{
|
{
|
||||||
if (null === $savePath) {
|
if (null === $savePath) {
|
||||||
$savePath = ini_get('session.save_path');
|
$savePath = \ini_get('session.save_path');
|
||||||
}
|
}
|
||||||
|
|
||||||
$baseDir = $savePath;
|
$baseDir = $savePath;
|
||||||
|
|
|
||||||
|
|
@ -344,7 +344,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
||||||
*/
|
*/
|
||||||
protected function doWrite(string $sessionId, string $data)
|
protected function doWrite(string $sessionId, string $data)
|
||||||
{
|
{
|
||||||
$maxlifetime = (int) ini_get('session.gc_maxlifetime');
|
$maxlifetime = (int) \ini_get('session.gc_maxlifetime');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// We use a single MERGE SQL query when supported by the database.
|
// We use a single MERGE SQL query when supported by the database.
|
||||||
|
|
@ -391,7 +391,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
||||||
#[\ReturnTypeWillChange]
|
#[\ReturnTypeWillChange]
|
||||||
public function updateTimestamp($sessionId, $data)
|
public function updateTimestamp($sessionId, $data)
|
||||||
{
|
{
|
||||||
$expiry = time() + (int) ini_get('session.gc_maxlifetime');
|
$expiry = time() + (int) \ini_get('session.gc_maxlifetime');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$updateStmt = $this->pdo->prepare(
|
$updateStmt = $this->pdo->prepare(
|
||||||
|
|
@ -687,7 +687,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
||||||
throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.');
|
throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!filter_var(ini_get('session.use_strict_mode'), \FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) {
|
if (!filter_var(\ini_get('session.use_strict_mode'), \FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) {
|
||||||
// In strict mode, session fixation is not possible: new sessions always start with a unique
|
// In strict mode, session fixation is not possible: new sessions always start with a unique
|
||||||
// random id, so that concurrency is not possible and this code path can be skipped.
|
// random id, so that concurrency is not possible and this code path can be skipped.
|
||||||
// Exclusive-reading of non-existent rows does not block, so we need to do an insert to block
|
// Exclusive-reading of non-existent rows does not block, so we need to do an insert to block
|
||||||
|
|
@ -935,7 +935,7 @@ class PdoSessionHandler extends AbstractSessionHandler
|
||||||
protected function getConnection()
|
protected function getConnection()
|
||||||
{
|
{
|
||||||
if (null === $this->pdo) {
|
if (null === $this->pdo) {
|
||||||
$this->connect($this->dsn ?: ini_get('session.save_path'));
|
$this->connect($this->dsn ?: \ini_get('session.save_path'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->pdo;
|
return $this->pdo;
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ class RedisSessionHandler extends AbstractSessionHandler
|
||||||
*/
|
*/
|
||||||
protected function doWrite(string $sessionId, string $data): bool
|
protected function doWrite(string $sessionId, string $data): bool
|
||||||
{
|
{
|
||||||
$result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime')), $data);
|
$result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')), $data);
|
||||||
|
|
||||||
return $result && !$result instanceof ErrorInterface;
|
return $result && !$result instanceof ErrorInterface;
|
||||||
}
|
}
|
||||||
|
|
@ -132,6 +132,6 @@ class RedisSessionHandler extends AbstractSessionHandler
|
||||||
#[\ReturnTypeWillChange]
|
#[\ReturnTypeWillChange]
|
||||||
public function updateTimestamp($sessionId, $data)
|
public function updateTimestamp($sessionId, $data)
|
||||||
{
|
{
|
||||||
return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime')));
|
return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,16 @@ class StrictSessionHandler extends AbstractSessionHandler
|
||||||
$this->handler = $handler;
|
$this->handler = $handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this handler wraps an internal PHP session save handler using \SessionHandler.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public function isWrapper(): bool
|
||||||
|
{
|
||||||
|
return $this->handler instanceof \SessionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,6 @@ class MetadataBag implements SessionBagInterface
|
||||||
{
|
{
|
||||||
$timeStamp = time();
|
$timeStamp = time();
|
||||||
$this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp;
|
$this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp;
|
||||||
$this->meta[self::LIFETIME] = $lifetime ?? (int) ini_get('session.cookie_lifetime');
|
$this->meta[self::LIFETIME] = $lifetime ?? (int) \ini_get('session.cookie_lifetime');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,12 +141,42 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||||
throw new \RuntimeException('Failed to start the session: already started by PHP.');
|
throw new \RuntimeException('Failed to start the session: already started by PHP.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter_var(ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) {
|
if (filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) {
|
||||||
throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line));
|
throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line));
|
||||||
}
|
}
|
||||||
|
|
||||||
$sessionId = $_COOKIE[session_name()] ?? null;
|
$sessionId = $_COOKIE[session_name()] ?? null;
|
||||||
if ($sessionId && $this->saveHandler instanceof AbstractProxy && 'files' === $this->saveHandler->getSaveHandlerName() && !preg_match('/^[a-zA-Z0-9,-]{22,}$/', $sessionId)) {
|
/*
|
||||||
|
* Explanation of the session ID regular expression: `/^[a-zA-Z0-9,-]{22,250}$/`.
|
||||||
|
*
|
||||||
|
* ---------- Part 1
|
||||||
|
*
|
||||||
|
* The part `[a-zA-Z0-9,-]` is related to the PHP ini directive `session.sid_bits_per_character` defined as 6.
|
||||||
|
* See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-bits-per-character.
|
||||||
|
* Allowed values are integers such as:
|
||||||
|
* - 4 for range `a-f0-9`
|
||||||
|
* - 5 for range `a-v0-9`
|
||||||
|
* - 6 for range `a-zA-Z0-9,-`
|
||||||
|
*
|
||||||
|
* ---------- Part 2
|
||||||
|
*
|
||||||
|
* The part `{22,250}` is related to the PHP ini directive `session.sid_length`.
|
||||||
|
* See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-length.
|
||||||
|
* Allowed values are integers between 22 and 256, but we use 250 for the max.
|
||||||
|
*
|
||||||
|
* Where does the 250 come from?
|
||||||
|
* - The length of Windows and Linux filenames is limited to 255 bytes. Then the max must not exceed 255.
|
||||||
|
* - The session filename prefix is `sess_`, a 5 bytes string. Then the max must not exceed 255 - 5 = 250.
|
||||||
|
*
|
||||||
|
* ---------- Conclusion
|
||||||
|
*
|
||||||
|
* The parts 1 and 2 prevent the warning below:
|
||||||
|
* `PHP Warning: SessionHandler::read(): Session ID is too long or contains illegal characters. Only the A-Z, a-z, 0-9, "-", and "," characters are allowed.`
|
||||||
|
*
|
||||||
|
* The part 2 prevents the warning below:
|
||||||
|
* `PHP Warning: SessionHandler::read(): open(filepath, O_RDWR) failed: No such file or directory (2).`
|
||||||
|
*/
|
||||||
|
if ($sessionId && $this->saveHandler instanceof AbstractProxy && 'files' === $this->saveHandler->getSaveHandlerName() && !preg_match('/^[a-zA-Z0-9,-]{22,250}$/', $sessionId)) {
|
||||||
// the session ID in the header is invalid, create a new one
|
// the session ID in the header is invalid, create a new one
|
||||||
session_id(session_create_id());
|
session_id(session_create_id());
|
||||||
}
|
}
|
||||||
|
|
@ -214,7 +244,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null !== $lifetime && $lifetime != ini_get('session.cookie_lifetime')) {
|
if (null !== $lifetime && $lifetime != \ini_get('session.cookie_lifetime')) {
|
||||||
$this->save();
|
$this->save();
|
||||||
ini_set('session.cookie_lifetime', $lifetime);
|
ini_set('session.cookie_lifetime', $lifetime);
|
||||||
$this->start();
|
$this->start();
|
||||||
|
|
@ -249,7 +279,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
||||||
unset($_SESSION[$key]);
|
unset($_SESSION[$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ([$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) {
|
if ($_SESSION && [$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) {
|
||||||
unset($_SESSION[$key]);
|
unset($_SESSION[$key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy;
|
namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Drak <drak@zikula.org>
|
* @author Drak <drak@zikula.org>
|
||||||
*/
|
*/
|
||||||
|
|
@ -22,7 +24,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf
|
||||||
{
|
{
|
||||||
$this->handler = $handler;
|
$this->handler = $handler;
|
||||||
$this->wrapper = $handler instanceof \SessionHandler;
|
$this->wrapper = $handler instanceof \SessionHandler;
|
||||||
$this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user';
|
$this->saveHandlerName = $this->wrapper || ($handler instanceof StrictSessionHandler && $handler->isWrapper()) ? \ini_get('session.save_handler') : 'user';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,11 @@
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"predis/predis": "~1.0",
|
"predis/predis": "~1.0",
|
||||||
"symfony/cache": "^4.4|^5.0|^6.0",
|
"symfony/cache": "^4.4|^5.0|^6.0",
|
||||||
|
"symfony/dependency-injection": "^5.4|^6.0",
|
||||||
|
"symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4",
|
||||||
"symfony/mime": "^4.4|^5.0|^6.0",
|
"symfony/mime": "^4.4|^5.0|^6.0",
|
||||||
"symfony/expression-language": "^4.4|^5.0|^6.0"
|
"symfony/expression-language": "^4.4|^5.0|^6.0",
|
||||||
|
"symfony/rate-limiter": "^5.2|^6.0"
|
||||||
},
|
},
|
||||||
"suggest" : {
|
"suggest" : {
|
||||||
"symfony/mime": "To use the file extension guesser"
|
"symfony/mime": "To use the file extension guesser"
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class ArgsStub extends EnumStub
|
||||||
|
|
||||||
$values = [];
|
$values = [];
|
||||||
foreach ($args as $k => $v) {
|
foreach ($args as $k => $v) {
|
||||||
$values[$k] = !is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v;
|
$values[$k] = !\is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v;
|
||||||
}
|
}
|
||||||
if (null === $params) {
|
if (null === $params) {
|
||||||
parent::__construct($values, false);
|
parent::__construct($values, false);
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ class IntlCaster
|
||||||
'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL),
|
'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL),
|
||||||
'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL),
|
'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
return self::castError($c, $a);
|
return self::castError($c, $a);
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
||||||
public function __construct($output = null, string $charset = null, int $flags = 0)
|
public function __construct($output = null, string $charset = null, int $flags = 0)
|
||||||
{
|
{
|
||||||
$this->flags = $flags;
|
$this->flags = $flags;
|
||||||
$this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8');
|
$this->setCharset($charset ?: \ini_get('php.output_encoding') ?: \ini_get('default_charset') ?: 'UTF-8');
|
||||||
$this->decimalPoint = \PHP_VERSION_ID >= 80000 ? '.' : localeconv()['decimal_point'];
|
$this->decimalPoint = \PHP_VERSION_ID >= 80000 ? '.' : localeconv()['decimal_point'];
|
||||||
$this->setOutput($output ?: static::$defaultOutput);
|
$this->setOutput($output ?: static::$defaultOutput);
|
||||||
if (!$output && \is_string(static::$defaultOutput)) {
|
if (!$output && \is_string(static::$defaultOutput)) {
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ class CliDumper extends AbstractDumper
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l';
|
$this->displayOptions['fileLinkFormat'] = \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ class HtmlDumper extends CliDumper
|
||||||
{
|
{
|
||||||
AbstractDumper::__construct($output, $charset, $flags);
|
AbstractDumper::__construct($output, $charset, $flags);
|
||||||
$this->dumpId = 'sf-dump-'.mt_rand();
|
$this->dumpId = 'sf-dump-'.mt_rand();
|
||||||
$this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
$this->displayOptions['fileLinkFormat'] = \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
||||||
$this->styles = static::$themes['dark'] ?? self::$themes['dark'];
|
$this->styles = static::$themes['dark'] ?? self::$themes['dark'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -882,7 +882,7 @@ EOHTML
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('const' === $style && isset($attr['value'])) {
|
if ('const' === $style && isset($attr['value'])) {
|
||||||
$style .= sprintf(' title="%s"', esc(is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value'])));
|
$style .= sprintf(' title="%s"', esc(\is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value'])));
|
||||||
} elseif ('public' === $style) {
|
} elseif ('public' === $style) {
|
||||||
$style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property');
|
$style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property');
|
||||||
} elseif ('str' === $style && 1 < $attr['length']) {
|
} elseif ('str' === $style && 1 < $attr['length']) {
|
||||||
|
|
|
||||||
|
|
@ -5,3 +5,6 @@ composer.lock
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
/.idea
|
/.idea
|
||||||
/.vscode
|
/.vscode
|
||||||
|
/.settings
|
||||||
|
/.buildpath
|
||||||
|
/.project
|
||||||
|
|
@ -58,10 +58,11 @@ if (!function_exists('abort')) {
|
||||||
if (!function_exists('app')) {
|
if (!function_exists('app')) {
|
||||||
/**
|
/**
|
||||||
* 快速获取容器中的实例 支持依赖注入
|
* 快速获取容器中的实例 支持依赖注入
|
||||||
* @param string $name 类名或标识 默认获取当前应用实例
|
* @template T
|
||||||
* @param array $args 参数
|
* @param string|class-string<T> $name 类名或标识 默认获取当前应用实例
|
||||||
* @param bool $newInstance 是否每次创建新的实例
|
* @param array $args 参数
|
||||||
* @return object|App
|
* @param bool $newInstance 是否每次创建新的实例
|
||||||
|
* @return T|object|App
|
||||||
*/
|
*/
|
||||||
function app(string $name = '', array $args = [], bool $newInstance = false)
|
function app(string $name = '', array $args = [], bool $newInstance = false)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ use think\initializer\RegisterService;
|
||||||
*/
|
*/
|
||||||
class App extends Container
|
class App extends Container
|
||||||
{
|
{
|
||||||
const VERSION = '6.0.12LTS';
|
const VERSION = '6.0.13LTS';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用调试模式
|
* 应用调试模式
|
||||||
|
|
|
||||||
|
|
@ -108,11 +108,11 @@ class Container implements ContainerInterface, ArrayAccess, IteratorAggregate, C
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取容器中的对象实例 不存在则创建
|
* 获取容器中的对象实例 不存在则创建
|
||||||
* @access public
|
* @template T
|
||||||
* @param string $abstract 类名或者标识
|
* @param string|class-string<T> $abstract 类名或者标识
|
||||||
* @param array|true $vars 变量
|
* @param array $vars 变量
|
||||||
* @param bool $newInstance 是否每次创建新的实例
|
* @param bool $newInstance 是否每次创建新的实例
|
||||||
* @return object
|
* @return T|object
|
||||||
*/
|
*/
|
||||||
public static function pull(string $abstract, array $vars = [], bool $newInstance = false)
|
public static function pull(string $abstract, array $vars = [], bool $newInstance = false)
|
||||||
{
|
{
|
||||||
|
|
@ -121,9 +121,9 @@ class Container implements ContainerInterface, ArrayAccess, IteratorAggregate, C
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取容器中的对象实例
|
* 获取容器中的对象实例
|
||||||
* @access public
|
* @template T
|
||||||
* @param string $abstract 类名或者标识
|
* @param string|class-string<T> $abstract 类名或者标识
|
||||||
* @return object
|
* @return T|object
|
||||||
*/
|
*/
|
||||||
public function get($abstract)
|
public function get($abstract)
|
||||||
{
|
{
|
||||||
|
|
@ -232,11 +232,11 @@ class Container implements ContainerInterface, ArrayAccess, IteratorAggregate, C
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建类的实例 已经存在则直接获取
|
* 创建类的实例 已经存在则直接获取
|
||||||
* @access public
|
* @template T
|
||||||
* @param string $abstract 类名或者标识
|
* @param string|class-string<T> $abstract 类名或者标识
|
||||||
* @param array $vars 变量
|
* @param array $vars 变量
|
||||||
* @param bool $newInstance 是否每次创建新的实例
|
* @param bool $newInstance 是否每次创建新的实例
|
||||||
* @return mixed
|
* @return T|object
|
||||||
*/
|
*/
|
||||||
public function make(string $abstract, array $vars = [], bool $newInstance = false)
|
public function make(string $abstract, array $vars = [], bool $newInstance = false)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,8 @@ class Lang
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->setLangSet($langset);
|
||||||
|
|
||||||
// 加载系统语言包
|
// 加载系统语言包
|
||||||
$this->load([
|
$this->load([
|
||||||
$this->app->getThinkPath() . 'lang' . DIRECTORY_SEPARATOR . $langset . '.php',
|
$this->app->getThinkPath() . 'lang' . DIRECTORY_SEPARATOR . $langset . '.php',
|
||||||
|
|
|
||||||
|
|
@ -1237,7 +1237,7 @@ class Request implements ArrayAccess
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $name header名称
|
* @param string $name header名称
|
||||||
* @param string $default 默认值
|
* @param string $default 默认值
|
||||||
* @return string|array
|
* @return string|array|null
|
||||||
*/
|
*/
|
||||||
public function header(string $name = '', string $default = null)
|
public function header(string $name = '', string $default = null)
|
||||||
{
|
{
|
||||||
|
|
@ -1416,6 +1416,10 @@ class Request implements ArrayAccess
|
||||||
foreach ($filters as $filter) {
|
foreach ($filters as $filter) {
|
||||||
if (is_callable($filter)) {
|
if (is_callable($filter)) {
|
||||||
// 调用函数或者方法过滤
|
// 调用函数或者方法过滤
|
||||||
|
if (is_null($value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$value = call_user_func($filter, $value);
|
$value = call_user_func($filter, $value);
|
||||||
} elseif (is_scalar($value)) {
|
} elseif (is_scalar($value)) {
|
||||||
if (is_string($filter) && false !== strpos($filter, '/')) {
|
if (is_string($filter) && false !== strpos($filter, '/')) {
|
||||||
|
|
@ -1490,7 +1494,7 @@ class Request implements ArrayAccess
|
||||||
if (is_int($key)) {
|
if (is_int($key)) {
|
||||||
$default = null;
|
$default = null;
|
||||||
$key = $val;
|
$key = $val;
|
||||||
if (!isset($data[$key])) {
|
if (!key_exists($key, $data)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,8 @@ class Route
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->config = array_merge($this->config, $this->app->config->get('route'));
|
$this->config = array_merge($this->config, $this->app->config->get('route'));
|
||||||
|
|
||||||
|
$this->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function init()
|
protected function init()
|
||||||
|
|
@ -630,6 +632,18 @@ class Route
|
||||||
return $this->rule($rule, $route, 'PATCH');
|
return $this->rule($rule, $route, 'PATCH');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册HEAD路由
|
||||||
|
* @access public
|
||||||
|
* @param string $rule 路由规则
|
||||||
|
* @param mixed $route 路由地址
|
||||||
|
* @return RuleItem
|
||||||
|
*/
|
||||||
|
public function head(string $rule, $route): RuleItem
|
||||||
|
{
|
||||||
|
return $this->rule($rule, $route, 'HEAD');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册OPTIONS路由
|
* 注册OPTIONS路由
|
||||||
* @access public
|
* @access public
|
||||||
|
|
@ -752,7 +766,6 @@ class Route
|
||||||
{
|
{
|
||||||
$this->request = $request;
|
$this->request = $request;
|
||||||
$this->host = $this->request->host(true);
|
$this->host = $this->request->host(true);
|
||||||
$this->init();
|
|
||||||
|
|
||||||
if ($withRoute) {
|
if ($withRoute) {
|
||||||
//加载路由
|
//加载路由
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,9 @@ abstract class Driver implements CacheInterface, CacheHandlerInterface
|
||||||
public function remember(string $name, $value, $expire = null)
|
public function remember(string $name, $value, $expire = null)
|
||||||
{
|
{
|
||||||
if ($this->has($name)) {
|
if ($this->has($name)) {
|
||||||
return $this->get($name);
|
if (($hit = $this->get($name)) !== null) {
|
||||||
|
return $hit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$time = time();
|
$time = time();
|
||||||
|
|
|
||||||
|
|
@ -214,12 +214,12 @@ class Console
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取终端模式
|
* 获取终端模式
|
||||||
* @return string <width>x<height> 或 null
|
* @return string <width>x<height>
|
||||||
*/
|
*/
|
||||||
private function getMode()
|
private function getMode()
|
||||||
{
|
{
|
||||||
if (!function_exists('proc_open')) {
|
if (!function_exists('proc_open')) {
|
||||||
return;
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
|
$descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
|
||||||
|
|
@ -234,7 +234,8 @@ class Console
|
||||||
return $matches[2] . 'x' . $matches[1];
|
return $matches[2] . 'x' . $matches[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function stringWidth(string $string): int
|
private function stringWidth(string $string): int
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ use think\route\Url as UrlBuild;
|
||||||
* @method static RuleItem put(string $rule, mixed $route) 注册PUT路由
|
* @method static RuleItem put(string $rule, mixed $route) 注册PUT路由
|
||||||
* @method static RuleItem delete(string $rule, mixed $route) 注册DELETE路由
|
* @method static RuleItem delete(string $rule, mixed $route) 注册DELETE路由
|
||||||
* @method static RuleItem patch(string $rule, mixed $route) 注册PATCH路由
|
* @method static RuleItem patch(string $rule, mixed $route) 注册PATCH路由
|
||||||
|
* @method static RuleItem head(string $rule, mixed $route) 注册HEAD路由
|
||||||
* @method static RuleItem options(string $rule, mixed $route) 注册OPTIONS路由
|
* @method static RuleItem options(string $rule, mixed $route) 注册OPTIONS路由
|
||||||
* @method static Resource resource(string $rule, string $route) 注册资源路由
|
* @method static Resource resource(string $rule, string $route) 注册资源路由
|
||||||
* @method static RuleItem view(string $rule, string $template = '', array $vars = []) 注册视图路由
|
* @method static RuleItem view(string $rule, string $template = '', array $vars = []) 注册视图路由
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,15 @@ class Local extends Driver
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件访问地址
|
||||||
|
* @param string $path 文件路径
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function url(string $path): string
|
public function url(string $path): string
|
||||||
{
|
{
|
||||||
|
$path = str_replace('\\', '/', $path);
|
||||||
|
|
||||||
if (isset($this->config['url'])) {
|
if (isset($this->config['url'])) {
|
||||||
return $this->concatPathToUrl($this->config['url'], $path);
|
return $this->concatPathToUrl($this->config['url'], $path);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,9 +74,9 @@ class Redirect extends Response
|
||||||
* @access public
|
* @access public
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function remember()
|
public function remember($complete = false)
|
||||||
{
|
{
|
||||||
$this->session->set('redirect_url', $this->request->url());
|
$this->session->set('redirect_url', $this->request->url($complete));
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ abstract class Dispatch
|
||||||
if ($data instanceof Response) {
|
if ($data instanceof Response) {
|
||||||
$response = $data;
|
$response = $data;
|
||||||
} elseif ($data instanceof ResponseInterface) {
|
} elseif ($data instanceof ResponseInterface) {
|
||||||
$response = Response::create($data->getBody()->getContents(), 'html', $data->getStatusCode());
|
$response = Response::create((string) $data->getBody(), 'html', $data->getStatusCode());
|
||||||
|
|
||||||
foreach ($data->getHeaders() as $header => $values) {
|
foreach ($data->getHeaders() as $header => $values) {
|
||||||
$response->header([$header => implode(", ", $values)]);
|
$response->header([$header => implode(", ", $values)]);
|
||||||
|
|
|
||||||
|
|
@ -492,7 +492,7 @@ if (!function_exists('echo_value')) {
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
$.getScript('//cdn.bootcss.com/prettify/r298/prettify.min.js', function(){
|
$.getScript('//cdn.bootcdn.net/ajax/libs/prettify/r298/prettify.min.js', function(){
|
||||||
prettyPrint();
|
prettyPrint();
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@
|
||||||
"php": ">=7.1.0",
|
"php": ">=7.1.0",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
"psr/simple-cache": "^1.0",
|
"psr/simple-cache": "^1.0|^2.0",
|
||||||
"psr/log": "~1.0",
|
"psr/log": "^1.0|^2.0",
|
||||||
"topthink/think-helper":"^3.1"
|
"topthink/think-helper":"^3.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
|
|
||||||
|
|
@ -628,7 +628,7 @@ abstract class BaseQuery
|
||||||
if (!isset($total) && !$simple) {
|
if (!isset($total) && !$simple) {
|
||||||
$options = $this->getOptions();
|
$options = $this->getOptions();
|
||||||
|
|
||||||
unset($this->options['order'], $this->options['limit'], $this->options['page'], $this->options['field']);
|
unset($this->options['order'], $this->options['cache'], $this->options['limit'], $this->options['page'], $this->options['field']);
|
||||||
|
|
||||||
$bind = $this->bind;
|
$bind = $this->bind;
|
||||||
$total = $this->count();
|
$total = $this->count();
|
||||||
|
|
@ -705,7 +705,7 @@ abstract class BaseQuery
|
||||||
->limit(1)
|
->limit(1)
|
||||||
->find();
|
->find();
|
||||||
|
|
||||||
$result = $data[$key];
|
$result = $data[$key] ?? 0;
|
||||||
|
|
||||||
if (is_numeric($result)) {
|
if (is_numeric($result)) {
|
||||||
$lastId = 'asc' == $sort ? ($result - 1) + ($page - 1) * $listRows : ($result + 1) - ($page - 1) * $listRows;
|
$lastId = 'asc' == $sort ? ($result - 1) + ($page - 1) * $listRows : ($result + 1) - ($page - 1) * $listRows;
|
||||||
|
|
|
||||||
|
|
@ -1274,7 +1274,7 @@ abstract class PDOConnection extends Connection
|
||||||
$type = is_array($val) ? $val[1] : PDO::PARAM_STR;
|
$type = is_array($val) ? $val[1] : PDO::PARAM_STR;
|
||||||
|
|
||||||
if (self::PARAM_FLOAT == $type || PDO::PARAM_STR == $type) {
|
if (self::PARAM_FLOAT == $type || PDO::PARAM_STR == $type) {
|
||||||
$value = '\'' . addcslashes($value, "'") . '\'';
|
$value = '\'' . addslashes($value) . '\'';
|
||||||
} elseif (PDO::PARAM_INT == $type && '' === $value) {
|
} elseif (PDO::PARAM_INT == $type && '' === $value) {
|
||||||
$value = '0';
|
$value = '0';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ namespace think\db\builder;
|
||||||
|
|
||||||
use think\db\Builder;
|
use think\db\Builder;
|
||||||
use think\db\Query;
|
use think\db\Query;
|
||||||
|
use think\db\exception\DbException as Exception;
|
||||||
|
use think\db\Raw;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Oracle数据库驱动
|
* Oracle数据库驱动
|
||||||
|
|
@ -64,19 +66,51 @@ class Oracle extends Builder
|
||||||
/**
|
/**
|
||||||
* 字段和表名处理
|
* 字段和表名处理
|
||||||
* @access public
|
* @access public
|
||||||
* @param Query $query 查询对象
|
* @param Query $query 查询对象
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $strict
|
* @param bool $strict
|
||||||
* @return string
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function parseKey(Query $query, $key, bool $strict = false): string
|
public function parseKey(Query $query, $key, bool $strict = false): string
|
||||||
{
|
{
|
||||||
|
if (is_int($key)) {
|
||||||
|
return (string) $key;
|
||||||
|
} elseif ($key instanceof Raw) {
|
||||||
|
return $this->parseRaw($query, $key);
|
||||||
|
}
|
||||||
|
|
||||||
$key = trim($key);
|
$key = trim($key);
|
||||||
|
|
||||||
if (strpos($key, '->') && false === strpos($key, '(')) {
|
if (strpos($key, '->') && false === strpos($key, '(')) {
|
||||||
// JSON字段支持
|
// JSON字段支持
|
||||||
[$field, $name] = explode($key, '->');
|
[$field, $name] = explode($key, '->');
|
||||||
$key = $field . '."' . $name . '"';
|
$key = $field . '."' . $name . '"';
|
||||||
|
} elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)\[\s]/', $key)) {
|
||||||
|
[$table, $key] = explode('.', $key, 2);
|
||||||
|
|
||||||
|
$alias = $query->getOptions('alias');
|
||||||
|
|
||||||
|
if ('__TABLE__' == $table) {
|
||||||
|
$table = $query->getOptions('table');
|
||||||
|
$table = is_array($table) ? array_shift($table) : $table;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($alias[$table])) {
|
||||||
|
$table = $alias[$table];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($strict && !preg_match('/^[\w\.\*]+$/', $key)) {
|
||||||
|
throw new Exception('not support data:' . $key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('*' != $key && !preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) {
|
||||||
|
$key = '"' . $key . '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($table)) {
|
||||||
|
$key = '"' . $table . '".' . $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $key;
|
return $key;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ declare (strict_types = 1);
|
||||||
|
|
||||||
namespace think\db\concern;
|
namespace think\db\concern;
|
||||||
|
|
||||||
|
use think\db\exception\DbException;
|
||||||
use think\db\Raw;
|
use think\db\Raw;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -42,6 +43,11 @@ trait AggregateQuery
|
||||||
{
|
{
|
||||||
if (!empty($this->options['group'])) {
|
if (!empty($this->options['group'])) {
|
||||||
// 支持GROUP
|
// 支持GROUP
|
||||||
|
|
||||||
|
if (!preg_match('/^[\w\.\*]+$/', $field)) {
|
||||||
|
throw new DbException('not support data:' . $field);
|
||||||
|
}
|
||||||
|
|
||||||
$options = $this->getOptions();
|
$options = $this->getOptions();
|
||||||
$subSql = $this->options($options)
|
$subSql = $this->options($options)
|
||||||
->field('count(' . $field . ') AS think_count')
|
->field('count(' . $field . ') AS think_count')
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ class Oracle extends PDOConnection
|
||||||
public function getFields(string $tableName): array
|
public function getFields(string $tableName): array
|
||||||
{
|
{
|
||||||
[$tableName] = explode(' ', $tableName);
|
[$tableName] = explode(' ', $tableName);
|
||||||
$sql = "select a.column_name,data_type,DECODE (nullable, 'Y', 0, 1) notnull,data_default, DECODE (A .column_name,b.column_name,1,0) pk from all_tab_columns a,(select column_name from all_constraints c, all_cons_columns col where c.constraint_name = col.constraint_name and c.constraint_type = 'P' and c.table_name = '" . strtoupper($tableName) . "' ) b where table_name = '" . strtoupper($tableName) . "' and a.column_name = b.column_name (+)";
|
$sql = "select a.column_name,data_type,DECODE (nullable, 'Y', 0, 1) notnull,data_default, DECODE (A .column_name,b.column_name,1,0) pk from all_tab_columns a,(select column_name from all_constraints c, all_cons_columns col where c.constraint_name = col.constraint_name and c.constraint_type = 'P' and c.table_name = '" . $tableName . "' ) b where table_name = '" . $tableName . "' and a.column_name = b.column_name (+)";
|
||||||
|
|
||||||
$pdo = $this->getPDOStatement($sql);
|
$pdo = $this->getPDOStatement($sql);
|
||||||
$result = $pdo->fetchAll(PDO::FETCH_ASSOC);
|
$result = $pdo->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
@ -98,16 +98,18 @@ class Oracle extends PDOConnection
|
||||||
/**
|
/**
|
||||||
* 获取最近插入的ID
|
* 获取最近插入的ID
|
||||||
* @access public
|
* @access public
|
||||||
* @param BaseQuery $query 查询对象
|
* @param BaseQuery $query 查询对象
|
||||||
* @param string $sequence 自增序列名
|
* @param string|null $sequence 自增序列名
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getLastInsID(BaseQuery $query, string $sequence = null)
|
public function getLastInsID(BaseQuery $query, string $sequence = null)
|
||||||
{
|
{
|
||||||
$pdo = $this->linkID->query("select {$sequence}.currval as id from dual");
|
if(!is_null($sequence)) {
|
||||||
$result = $pdo->fetchColumn();
|
$pdo = $this->linkID->query("select {$sequence}.currval as id from dual");
|
||||||
|
$result = $pdo->fetchColumn();
|
||||||
|
}
|
||||||
|
|
||||||
return $result;
|
return $result ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function supportSavepoint(): bool
|
protected function supportSavepoint(): bool
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,10 @@ class Sqlsrv extends PDOConnection
|
||||||
$dsn .= ',' . $config['hostport'];
|
$dsn .= ',' . $config['hostport'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($config['trust_server_certificate'])) {
|
||||||
|
$dsn .= ';TrustServerCertificate=' . $config['trust_server_certificate'];
|
||||||
|
}
|
||||||
|
|
||||||
return $dsn;
|
return $dsn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,13 @@ class Collection extends BaseCollection
|
||||||
* 设置需要隐藏的输出属性
|
* 设置需要隐藏的输出属性
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $hidden 属性列表
|
* @param array $hidden 属性列表
|
||||||
|
* @param bool $merge 是否合并
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function hidden(array $hidden)
|
public function hidden(array $hidden, bool $merge = false)
|
||||||
{
|
{
|
||||||
$this->each(function (Model $model) use ($hidden) {
|
$this->each(function (Model $model) use ($hidden, $merge) {
|
||||||
$model->hidden($hidden);
|
$model->hidden($hidden, $merge);
|
||||||
});
|
});
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
@ -96,12 +97,13 @@ class Collection extends BaseCollection
|
||||||
* 设置需要输出的属性
|
* 设置需要输出的属性
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $visible
|
* @param array $visible
|
||||||
|
* @param bool $merge 是否合并
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function visible(array $visible)
|
public function visible(array $visible, bool $merge = false)
|
||||||
{
|
{
|
||||||
$this->each(function (Model $model) use ($visible) {
|
$this->each(function (Model $model) use ($visible, $merge) {
|
||||||
$model->visible($visible);
|
$model->visible($visible, $merge);
|
||||||
});
|
});
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
@ -111,12 +113,13 @@ class Collection extends BaseCollection
|
||||||
* 设置需要追加的输出属性
|
* 设置需要追加的输出属性
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $append 属性列表
|
* @param array $append 属性列表
|
||||||
|
* @param bool $merge 是否合并
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function append(array $append)
|
public function append(array $append, bool $merge = false)
|
||||||
{
|
{
|
||||||
$this->each(function (Model $model) use ($append) {
|
$this->each(function (Model $model) use ($append, $merge) {
|
||||||
$model->append($append);
|
$model->append($append, $merge);
|
||||||
});
|
});
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,9 @@ class Pivot extends Model
|
||||||
/**
|
/**
|
||||||
* 架构函数
|
* 架构函数
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $data 数据
|
* @param array $data 数据
|
||||||
* @param Model $parent 上级模型
|
* @param Model|null $parent 上级模型
|
||||||
* @param string $table 中间数据表名
|
* @param string $table 中间数据表名
|
||||||
*/
|
*/
|
||||||
public function __construct(array $data = [], Model $parent = null, string $table = '')
|
public function __construct(array $data = [], Model $parent = null, string $table = '')
|
||||||
{
|
{
|
||||||
|
|
@ -50,4 +50,21 @@ class Pivot extends Model
|
||||||
parent::__construct($data);
|
parent::__construct($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建新的模型实例
|
||||||
|
* @access public
|
||||||
|
* @param array $data 数据
|
||||||
|
* @param mixed $where 更新条件
|
||||||
|
* @param array $options 参数
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
public function newInstance(array $data = [], $where = null, array $options = []): Model
|
||||||
|
{
|
||||||
|
$model = parent::newInstance($data, $where, $options);
|
||||||
|
|
||||||
|
$model->parent = $this->parent;
|
||||||
|
$model->name = $this->name;
|
||||||
|
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,11 +82,16 @@ trait Conversion
|
||||||
* 设置需要附加的输出属性
|
* 设置需要附加的输出属性
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $append 属性列表
|
* @param array $append 属性列表
|
||||||
|
* @param bool $merge 是否合并
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function append(array $append = [])
|
public function append(array $append = [], bool $merge = false)
|
||||||
{
|
{
|
||||||
$this->append = $append;
|
if ($merge) {
|
||||||
|
$this->append = array_merge($this->append, $append);
|
||||||
|
} else {
|
||||||
|
$this->append = $append;
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
@ -147,11 +152,16 @@ trait Conversion
|
||||||
* 设置需要隐藏的输出属性
|
* 设置需要隐藏的输出属性
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $hidden 属性列表
|
* @param array $hidden 属性列表
|
||||||
|
* @param bool $merge 是否合并
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function hidden(array $hidden = [])
|
public function hidden(array $hidden = [], bool $merge = false)
|
||||||
{
|
{
|
||||||
$this->hidden = $hidden;
|
if ($merge) {
|
||||||
|
$this->hidden = array_merge($this->hidden, $hidden);
|
||||||
|
} else {
|
||||||
|
$this->hidden = $hidden;
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
@ -160,11 +170,16 @@ trait Conversion
|
||||||
* 设置需要输出的属性
|
* 设置需要输出的属性
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $visible
|
* @param array $visible
|
||||||
|
* @param bool $merge 是否合并
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function visible(array $visible = [])
|
public function visible(array $visible = [], bool $merge = false)
|
||||||
{
|
{
|
||||||
$this->visible = $visible;
|
if ($merge) {
|
||||||
|
$this->visible = array_merge($this->visible, $visible);
|
||||||
|
} else {
|
||||||
|
$this->visible = $visible;
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,7 @@ class BelongsTo extends OneToOne
|
||||||
if (!empty($this->bindAttr)) {
|
if (!empty($this->bindAttr)) {
|
||||||
// 绑定关联属性
|
// 绑定关联属性
|
||||||
$this->bindAttr($result, $relationModel);
|
$this->bindAttr($result, $relationModel);
|
||||||
|
$result->hidden([$relation]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -282,6 +283,7 @@ class BelongsTo extends OneToOne
|
||||||
if (!empty($this->bindAttr)) {
|
if (!empty($this->bindAttr)) {
|
||||||
// 绑定关联属性
|
// 绑定关联属性
|
||||||
$this->bindAttr($result, $relationModel);
|
$this->bindAttr($result, $relationModel);
|
||||||
|
$result->hidden([$relation]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,12 @@ class BelongsToMany extends Relation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$result->setRelation($this->pivotDataName, $this->newPivot($pivot));
|
$pivotData = $this->pivot->newInstance($pivot, [
|
||||||
|
[$this->localKey, '=', $this->parent->getKey(), null],
|
||||||
|
[$this->foreignKey, '=', $result->getKey(), null],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$result->setRelation($this->pivotDataName, $pivotData);
|
||||||
return $pivot;
|
return $pivot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,7 @@ class HasOne extends OneToOne
|
||||||
if (!empty($this->bindAttr)) {
|
if (!empty($this->bindAttr)) {
|
||||||
// 绑定关联属性
|
// 绑定关联属性
|
||||||
$this->bindAttr($result, $relationModel);
|
$this->bindAttr($result, $relationModel);
|
||||||
|
$result->hidden([$relation]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -281,6 +282,7 @@ class HasOne extends OneToOne
|
||||||
if (!empty($this->bindAttr)) {
|
if (!empty($this->bindAttr)) {
|
||||||
// 绑定关联属性
|
// 绑定关联属性
|
||||||
$this->bindAttr($result, $relationModel);
|
$this->bindAttr($result, $relationModel);
|
||||||
|
$result->hidden([$relation]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ class MorphMany extends Relation
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $morphKey;
|
protected $morphKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多态字段名
|
* 多态字段名
|
||||||
* @var string
|
* @var string
|
||||||
|
|
@ -331,6 +332,33 @@ class MorphMany extends Relation
|
||||||
return empty($result) ? false : $result;
|
return empty($result) ? false : $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取多态关联外键
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMorphKey()
|
||||||
|
{
|
||||||
|
return $this->morphKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取多态字段名
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMorphType()
|
||||||
|
{
|
||||||
|
return $this->morphType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取多态类型
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行基础查询(仅执行一次)
|
* 执行基础查询(仅执行一次)
|
||||||
* @access protected
|
* @access protected
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,9 @@ class MorphTo extends Relation
|
||||||
// 多态类型映射
|
// 多态类型映射
|
||||||
$model = $this->parseModel($key);
|
$model = $this->parseModel($key);
|
||||||
$obj = new $model;
|
$obj = new $model;
|
||||||
|
if (!\is_null($closure)) {
|
||||||
|
$obj = $closure($obj);
|
||||||
|
}
|
||||||
$pk = $obj->getPk();
|
$pk = $obj->getPk();
|
||||||
$list = $obj->with($subRelation)
|
$list = $obj->with($subRelation)
|
||||||
->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null)
|
->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null)
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,13 @@ use think\model\Pivot;
|
||||||
class MorphToMany extends BelongsToMany
|
class MorphToMany extends BelongsToMany
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多态关系的模型名映射别名的数组
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static $morphMap = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多态字段名
|
* 多态字段名
|
||||||
* @var string
|
* @var string
|
||||||
|
|
@ -58,6 +65,9 @@ class MorphToMany extends BelongsToMany
|
||||||
$this->morphType = $morphType;
|
$this->morphType = $morphType;
|
||||||
$this->inverse = $inverse;
|
$this->inverse = $inverse;
|
||||||
$this->morphClass = $inverse ? $model : get_class($parent);
|
$this->morphClass = $inverse ? $model : get_class($parent);
|
||||||
|
if (isset(static::$morphMap[$this->morphClass])) {
|
||||||
|
$this->morphClass = static::$morphMap[$this->morphClass];
|
||||||
|
}
|
||||||
|
|
||||||
$foreignKey = $inverse ? $morphKey : $localKey;
|
$foreignKey = $inverse ? $morphKey : $localKey;
|
||||||
$localKey = $inverse ? $localKey : $morphKey;
|
$localKey = $inverse ? $localKey : $morphKey;
|
||||||
|
|
@ -460,4 +470,21 @@ class MorphToMany extends BelongsToMany
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置或获取多态关系的模型名映射别名的数组
|
||||||
|
*
|
||||||
|
* @param array|null $map
|
||||||
|
* @param bool $merge
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function morphMap(array $map = null, $merge = true): array
|
||||||
|
{
|
||||||
|
if (is_array($map)) {
|
||||||
|
static::$morphMap = $merge && static::$morphMap
|
||||||
|
? $map + static::$morphMap : $map;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static::$morphMap;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -186,18 +186,30 @@ abstract class OneToOne extends Relation
|
||||||
* @return Model|false
|
* @return Model|false
|
||||||
*/
|
*/
|
||||||
public function save($data, bool $replace = true)
|
public function save($data, bool $replace = true)
|
||||||
|
{
|
||||||
|
$model = $this->make();
|
||||||
|
|
||||||
|
return $model->replace($replace)->save($data) ? $model : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建关联对象实例
|
||||||
|
* @param array|Model $data
|
||||||
|
* @return Model
|
||||||
|
*/
|
||||||
|
public function make($data = []): Model
|
||||||
{
|
{
|
||||||
if ($data instanceof Model) {
|
if ($data instanceof Model) {
|
||||||
$data = $data->getData();
|
$data = $data->getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
$model = new $this->model;
|
|
||||||
// 保存关联表数据
|
// 保存关联表数据
|
||||||
$data[$this->foreignKey] = $this->parent->{$this->localKey};
|
$data[$this->foreignKey] = $this->parent->{$this->localKey};
|
||||||
|
|
||||||
return $model->replace($replace)->save($data) ? $model : false;
|
return new $this->model($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定关联表的属性到父模型属性
|
* 绑定关联表的属性到父模型属性
|
||||||
* @access public
|
* @access public
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue