add migration for importing users and textures simultaneously
This commit is contained in:
parent
8970c17472
commit
0e3418dc56
|
|
@ -96,7 +96,7 @@ class SkinlibController extends BaseController
|
||||||
{
|
{
|
||||||
if (!isset($_GET['tid'])) Http::abort(404, 'No specified tid.');
|
if (!isset($_GET['tid'])) Http::abort(404, 'No specified tid.');
|
||||||
$texture = Texture::find($_GET['tid']);
|
$texture = Texture::find($_GET['tid']);
|
||||||
/*
|
|
||||||
if (!$texture || $texture && !\Storage::exist(BASE_DIR."/textures/".$texture->hash)) {
|
if (!$texture || $texture && !\Storage::exist(BASE_DIR."/textures/".$texture->hash)) {
|
||||||
if (Option::get('auto_del_invalid_texture') == "1") {
|
if (Option::get('auto_del_invalid_texture') == "1") {
|
||||||
if ($texture) $texture->delete();
|
if ($texture) $texture->delete();
|
||||||
|
|
@ -104,7 +104,7 @@ class SkinlibController extends BaseController
|
||||||
}
|
}
|
||||||
Http::abort(404, '请求的材质文件已经被删除,请联系管理员删除该条目');
|
Http::abort(404, '请求的材质文件已经被删除,请联系管理员删除该条目');
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
if ($texture->public == "0") {
|
if ($texture->public == "0") {
|
||||||
if (is_null($this->user) || ($this->user->uid != $texture->uploader && !$this->user->is_admin))
|
if (is_null($this->user) || ($this->user->uid != $texture->uploader && !$this->user->is_admin))
|
||||||
Http::abort(404, '请求的材质已经设为隐私,仅上传者和管理员可查看');
|
Http::abort(404, '请求的材质已经设为隐私,仅上传者和管理员可查看');
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,15 @@ class Storage
|
||||||
return $new_fname;
|
return $new_fname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function size($filename)
|
||||||
|
{
|
||||||
|
if (self::exist($filename)) {
|
||||||
|
return filesize($filename);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a file
|
* Remove a file
|
||||||
*
|
*
|
||||||
|
|
|
||||||
97
resources/views/setup/migrations/import-v2-both.tpl
Normal file
97
resources/views/setup/migrations/import-v2-both.tpl
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
@extends('setup.migrations.master')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<?php $step = isset($_GET['step']) ? $_GET['step'] : '1'; ?>
|
||||||
|
|
||||||
|
{{-- Step 1: --}}
|
||||||
|
|
||||||
|
@if ($step == '1')
|
||||||
|
<h1>同时导入用户数据以及用户材质</h1>
|
||||||
|
|
||||||
|
<p>将同时导入用户数据以及材质,逻辑比单独导入更加完善。</p>
|
||||||
|
<p>导入后材质的上传者将被设置为 v2 的原用户,上传时间将被设置为 v2 用户的最后修改时间。导入后的材质会被自动添加至原上传者的衣柜中,并应用至其所属角色。</p>
|
||||||
|
<p><b>注意:</b> 请先将 v2 的 users 表改名导入到当前 v3 的同一数据库中</p>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<form id="setup" method="post" action="index.php?action=import-v2-both&step=2" novalidate="novalidate">
|
||||||
|
<table class="form-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><label for="v2_table_name">v2 的用户表名</label></th>
|
||||||
|
<td>
|
||||||
|
<input name="v2_table_name" type="v2_table_name" id="v2_table_name" size="25" value="" />
|
||||||
|
<p>就是你改名过的 v2 的 users 表现在的名字</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><label for="texture_name_pattern">导入后的材质名称</label></th>
|
||||||
|
<td>
|
||||||
|
<input name="texture_name_pattern" type="text" id="texture_name_pattern" size="25" value="{username} - {model}" />
|
||||||
|
<p>
|
||||||
|
<span class="description important">
|
||||||
|
{username} 表示材质原本的上传者用户名,{model} 表示原来材质的模型
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th scope="row">私密材质</th>
|
||||||
|
<td>
|
||||||
|
<label for="import_as_private">
|
||||||
|
<input name="import_as_private" type="checkbox" id="import_as_private" size="25" /> 导入为私密材质
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
@if (isset($_SESSION['msg']))
|
||||||
|
<div class="alert alert-warning" role="alert">{{ htmlspecialchars($_SESSION['msg']) }}</div>
|
||||||
|
<?php unset($_SESSION['msg']); ?>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<p class="step">
|
||||||
|
<input type="submit" name="submit" id="submit" class="button button-large" value="开始迁移" />
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- Step 2: --}}
|
||||||
|
|
||||||
|
@if ($step == '2')
|
||||||
|
|
||||||
|
<?php
|
||||||
|
if (Validate::checkPost(['v2_table_name', 'texture_name_pattern'], true)) {
|
||||||
|
if ($_POST['v2_table_name'] == "") {
|
||||||
|
Http::redirect('index.php?action=import-v2-both&step=1', 'v2 users 表名不能为空');
|
||||||
|
} else {
|
||||||
|
if (Utils::convertString($_POST['v2_table_name']) != $_POST['v2_table_name'])
|
||||||
|
Http::redirect('index.php?action=import-v2-both&step=1', "表名 {$_POST['v2_table_name']} 中含有无效字符");
|
||||||
|
|
||||||
|
if (!Database::hasTable($_POST['v2_table_name'])) {
|
||||||
|
Http::redirect('index.php?action=import-v2-both&step=1', "数据表 {$_POST['v2_table_name']} 不存在");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Http::redirect('index.php?action=import-v2-both&step=1', '表单信息不完整');
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<h1>导入成功</h1>
|
||||||
|
|
||||||
|
<?php $result = Migration::importV2Both(); ?>
|
||||||
|
|
||||||
|
<p>已导入 {{ $result['user']['imported'] }} 个用户,{{ $result['user']['duplicated'] }} 个用户因重复而未导入。</p>
|
||||||
|
<p>已导入 {{ $result['texture']['imported'] }} 个材质到皮肤库,{{ $result['texture']['duplicated'] }} 个材质因重复而未导入。</p>
|
||||||
|
|
||||||
|
<p class="step">
|
||||||
|
<a href="../../" class="button button-large">导入完成</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<h1>导入皮肤库</h1>
|
<h1>导入皮肤库</h1>
|
||||||
|
|
||||||
<p>本功能用于导入 v2 用户皮肤至 v3 的皮肤库</p>
|
<p>本功能用于导入 v2 用户皮肤至 v3 的皮肤库</p>
|
||||||
<p>请先将 v2 的 users 表改名导入到当前 v3 的同一数据库中</p>
|
<p>注意:请先将 v2 的 users 表改名导入到当前 v3 的同一数据库中</p>
|
||||||
|
|
||||||
<form id="setup" method="post" action="index.php?action=import-v2-textures&step=2" novalidate="novalidate">
|
<form id="setup" method="post" action="index.php?action=import-v2-textures&step=2" novalidate="novalidate">
|
||||||
<table class="form-table">
|
<table class="form-table">
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
<h1>导入用户数据</h1>
|
<h1>导入用户数据</h1>
|
||||||
|
|
||||||
<p>本功能用于导入 v2 的用户账户数据至 v3,请先将 v2 的 users 表改名导入到当前 v3 的同一数据库中</p>
|
<p>本功能用于导入 v2 的用户账户数据至 v3,请先将 v2 的 users 表改名导入到当前 v3 的同一数据库中</p>
|
||||||
|
<p>仅导入用户数据将会丢失用户的材质信息,如需保存原来的材质信息,请 <a href="index.php?action=import-v2-both">同时导入用户和材质</a>。</p>
|
||||||
<p><b>注意:</b> v3 当前设置的密码加密方式必须和之前 v2 的一致,否则导入后的用户将无法登录。</p>
|
<p><b>注意:</b> v3 当前设置的密码加密方式必须和之前 v2 的一致,否则导入后的用户将无法登录。</p>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
|
||||||
|
|
@ -13,5 +13,6 @@
|
||||||
<p class="step">
|
<p class="step">
|
||||||
<a href="index.php?action=import-v2-textures" class="button button-large">导入 v2 皮肤库</a>
|
<a href="index.php?action=import-v2-textures" class="button button-large">导入 v2 皮肤库</a>
|
||||||
<a href="index.php?action=import-v2-users" class="button button-large">导入 v2 用户数据</a>
|
<a href="index.php?action=import-v2-users" class="button button-large">导入 v2 用户数据</a>
|
||||||
|
<a href="index.php?action=import-v2-both" class="button button-large">同时导入</a>
|
||||||
</p>
|
</p>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
139
setup/migrations/import_v2_both.php
Normal file
139
setup/migrations/import_v2_both.php
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @Author: printempw
|
||||||
|
* @Date: 2016-08-18 17:46:19
|
||||||
|
* @Last Modified by: printempw
|
||||||
|
* @Last Modified time: 2016-08-20 20:49:29
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('BASE_DIR')) exit('Permission denied.');
|
||||||
|
|
||||||
|
$v2_table_name = $_POST['v2_table_name'];
|
||||||
|
$prefix = Config::getDbConfig()['prefix'];
|
||||||
|
$v3_users = $prefix."users";
|
||||||
|
$v3_players = $prefix."players";
|
||||||
|
$v3_closets = $prefix."closets";
|
||||||
|
$v3_textures = $prefix."textures";
|
||||||
|
|
||||||
|
$user_imported = 0;
|
||||||
|
$user_duplicated = 0;
|
||||||
|
$texture_imported = 0;
|
||||||
|
$texture_duplicated = 0;
|
||||||
|
|
||||||
|
// use db helper instead of fat ORM in some operations :(
|
||||||
|
$db = Database::table($v2_table_name, true);
|
||||||
|
|
||||||
|
$steps = ceil($db->getRecordNum() / 250);
|
||||||
|
|
||||||
|
$score = Option::get('user_initial_score');
|
||||||
|
|
||||||
|
$public = isset($_POST['import_as_private']) ? '0' : '1';
|
||||||
|
|
||||||
|
// chunked (optionally)
|
||||||
|
for ($i = 0; $i <= $steps; $i++) {
|
||||||
|
$start = $i * 250;
|
||||||
|
|
||||||
|
$sql = "SELECT * FROM `$v2_table_name` ORDER BY `uid` LIMIT $start, 250";
|
||||||
|
$result = $db->query($sql);
|
||||||
|
|
||||||
|
while ($row = $result->fetch_array()) {
|
||||||
|
// compile patterns
|
||||||
|
$name = str_replace('{username}', $row['username'], $_POST['texture_name_pattern']);
|
||||||
|
|
||||||
|
if (!$db->has('player_name', $row['username'], $v3_players)) {
|
||||||
|
$user = new App\Models\UserModel;
|
||||||
|
|
||||||
|
$user->email = '';
|
||||||
|
$user->nickname = $row['username'];
|
||||||
|
$user->score = $score;
|
||||||
|
$user->password = $row['password'];
|
||||||
|
$user->avatar = '0';
|
||||||
|
$user->ip = $row['ip'];
|
||||||
|
$user->permission = '0';
|
||||||
|
$user->last_sign_at = Utils::getTimeFormatted(time() - 86400);
|
||||||
|
$user->register_at = Utils::getTimeFormatted();
|
||||||
|
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
$models = ['steve', 'alex', 'cape'];
|
||||||
|
|
||||||
|
$textures = [];
|
||||||
|
|
||||||
|
foreach ($models as $model) {
|
||||||
|
if ($row["hash_$model"] != "") {
|
||||||
|
$name = str_replace('{model}', $model, $name);
|
||||||
|
|
||||||
|
if (!$db->has('hash', $row["hash_$model"], $v3_textures)) {
|
||||||
|
$t = new App\Models\Texture;
|
||||||
|
|
||||||
|
$t->name = $name;
|
||||||
|
$t->type = $model;
|
||||||
|
$t->likes = 1;
|
||||||
|
$t->hash = $row["hash_$model"];
|
||||||
|
$t->size = Storage::size(BASE_DIR.'/textures/'.$row["hash_$model"]);
|
||||||
|
$t->uploader = $user->uid;
|
||||||
|
$t->public = $public;
|
||||||
|
$t->upload_at = $row['last_modified'] ? : Utils::getTimeFormatted();
|
||||||
|
|
||||||
|
$t->save();
|
||||||
|
|
||||||
|
$textures[$model] = $t->tid;
|
||||||
|
|
||||||
|
$texture_imported++;
|
||||||
|
} else {
|
||||||
|
$texture_duplicated++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$p = new App\Models\PlayerModel;
|
||||||
|
|
||||||
|
$p->uid = $user->uid;
|
||||||
|
$p->player_name = $row['username'];
|
||||||
|
$p->preference = $row['preference'];
|
||||||
|
$p->last_modified = $row['last_modified'] ? : Utils::getTimeFormatted();
|
||||||
|
|
||||||
|
$c = new App\Models\ClosetModel;
|
||||||
|
|
||||||
|
$c->uid = $user->uid;
|
||||||
|
$c->textures = '';
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
foreach ($textures as $model => $tid) {
|
||||||
|
$property = "tid_$model";
|
||||||
|
$p->$property = $tid;
|
||||||
|
|
||||||
|
$items[] = array(
|
||||||
|
'tid' => $tid,
|
||||||
|
'name' => $name,
|
||||||
|
'add_at' => $row['last_modified'] ? : Utils::getTimeFormatted()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$c->textures = json_encode($items);
|
||||||
|
|
||||||
|
$p->save();
|
||||||
|
$c->save();
|
||||||
|
|
||||||
|
$user_imported++;
|
||||||
|
// echo $row['username']." saved. <br />";
|
||||||
|
} else {
|
||||||
|
$user_duplicated++;
|
||||||
|
// echo $row['username']." duplicated. <br />";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'user' => [
|
||||||
|
'imported' => $user_imported,
|
||||||
|
'duplicated' => $user_duplicated
|
||||||
|
],
|
||||||
|
'texture' => [
|
||||||
|
'imported' => $texture_imported,
|
||||||
|
'duplicated' => $texture_duplicated
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* @Author: printempw
|
* @Author: printempw
|
||||||
* @Date: 2016-08-09 21:44:13
|
* @Date: 2016-08-09 21:44:13
|
||||||
* @Last Modified by: printempw
|
* @Last Modified by: printempw
|
||||||
* @Last Modified time: 2016-08-19 22:48:54
|
* @Last Modified time: 2016-08-20 20:49:37
|
||||||
*
|
*
|
||||||
* There are still some coupling relationships here but,
|
* There are still some coupling relationships here but,
|
||||||
* Just let it go :)
|
* Just let it go :)
|
||||||
|
|
@ -22,9 +22,9 @@ $db = Database::table($v2_table_name, true);
|
||||||
|
|
||||||
$steps = ceil($db->getRecordNum() / 250);
|
$steps = ceil($db->getRecordNum() / 250);
|
||||||
|
|
||||||
$public = isset($_POST['import_as_private']) ? '1' : '0';
|
$public = isset($_POST['import_as_private']) ? '0' : '1';
|
||||||
|
|
||||||
// chunked
|
// chunked (optionally)
|
||||||
for ($i = 0; $i <= $steps; $i++) {
|
for ($i = 0; $i <= $steps; $i++) {
|
||||||
$start = $i * 250;
|
$start = $i * 250;
|
||||||
|
|
||||||
|
|
@ -35,72 +35,30 @@ for ($i = 0; $i <= $steps; $i++) {
|
||||||
// compile patterns
|
// compile patterns
|
||||||
$name = str_replace('{username}', $row['username'], $_POST['texture_name_pattern']);
|
$name = str_replace('{username}', $row['username'], $_POST['texture_name_pattern']);
|
||||||
|
|
||||||
if ($row['hash_steve'] != "") {
|
$models = ['steve', 'alex', 'cape'];
|
||||||
$name = str_replace('{model}', 'steve', $name);
|
|
||||||
|
|
||||||
if (!$db->has('hash', $row['hash_steve'], $v3_table_name)) {
|
foreach ($models as $model) {
|
||||||
$db->insert([
|
if ($row['hash_steve'] != "") {
|
||||||
'name' => $name,
|
$name = str_replace('{model}', $model, $name);
|
||||||
'type' => 'steve',
|
|
||||||
'likes' => 0,
|
|
||||||
'hash' => $row['hash_steve'],
|
|
||||||
'size' => 0,
|
|
||||||
'uploader' => $_POST['uploader_uid'],
|
|
||||||
'public' => $public,
|
|
||||||
'upload_at' => Utils::getTimeFormatted()
|
|
||||||
], $v3_table_name);
|
|
||||||
|
|
||||||
$imported++;
|
if (!$db->has('hash', $row["hash_$model"], $v3_table_name)) {
|
||||||
// echo $row['hash_steve']." saved. <br />";
|
$db->insert([
|
||||||
} else {
|
'name' => $name,
|
||||||
$duplicated++;
|
'type' => $model,
|
||||||
// echo $row['hash_steve']." duplicated. <br />";
|
'likes' => 0,
|
||||||
}
|
'hash' => $row["hash_$model"],
|
||||||
}
|
'size' => Storage::size(BASE_DIR.'/textures/'.$row["hash_$model"]),
|
||||||
|
'uploader' => $_POST['uploader_uid'],
|
||||||
|
'public' => $public,
|
||||||
|
'upload_at' => Utils::getTimeFormatted()
|
||||||
|
], $v3_table_name);
|
||||||
|
|
||||||
if ($row['hash_alex'] != "") {
|
$imported++;
|
||||||
$name = str_replace('{model}', 'alex', $name);
|
// echo $row['hash_steve']." saved. <br />";
|
||||||
|
} else {
|
||||||
if (!$db->has('hash', $row['hash_alex'], $v3_table_name)) {
|
$duplicated++;
|
||||||
$db->insert([
|
// echo $row['hash_steve']." duplicated. <br />";
|
||||||
'name' => $name,
|
}
|
||||||
'type' => 'alex',
|
|
||||||
'likes' => 0,
|
|
||||||
'hash' => $row['hash_alex'],
|
|
||||||
'size' => 0,
|
|
||||||
'uploader' => $_POST['uploader_uid'],
|
|
||||||
'public' => $public,
|
|
||||||
'upload_at' => Utils::getTimeFormatted()
|
|
||||||
], $v3_table_name);
|
|
||||||
|
|
||||||
$imported++;
|
|
||||||
// echo $row['hash_alex']." saved. <br />";
|
|
||||||
} else {
|
|
||||||
$duplicated++;
|
|
||||||
// echo $row['hash_alex']." duplicated. <br />";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row['hash_cape'] != "") {
|
|
||||||
$name = str_replace('{model}', 'cape', $name);
|
|
||||||
|
|
||||||
if (!$db->has('hash', $row['hash_cape'], $v3_table_name)) {
|
|
||||||
$db->insert([
|
|
||||||
'name' => $name,
|
|
||||||
'type' => 'cape',
|
|
||||||
'likes' => 0,
|
|
||||||
'hash' => $row['hash_cape'],
|
|
||||||
'size' => 0,
|
|
||||||
'uploader' => $_POST['uploader_uid'],
|
|
||||||
'public' => $public,
|
|
||||||
'upload_at' => Utils::getTimeFormatted()
|
|
||||||
], $v3_table_name);
|
|
||||||
|
|
||||||
$imported++;
|
|
||||||
// echo $row['hash_cape']." saved. <br />";
|
|
||||||
} else {
|
|
||||||
$duplicated++;
|
|
||||||
// echo $row['hash_cape']." duplicated. <br />";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* @Author: printempw
|
* @Author: printempw
|
||||||
* @Date: 2016-08-18 17:46:19
|
* @Date: 2016-08-18 17:46:19
|
||||||
* @Last Modified by: printempw
|
* @Last Modified by: printempw
|
||||||
* @Last Modified time: 2016-08-19 22:00:02
|
* @Last Modified time: 2016-08-20 18:42:56
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!defined('BASE_DIR')) exit('Permission denied.');
|
if (!defined('BASE_DIR')) exit('Permission denied.');
|
||||||
|
|
@ -24,7 +24,7 @@ $steps = ceil($db->getRecordNum() / 250);
|
||||||
|
|
||||||
$score = Option::get('user_initial_score');
|
$score = Option::get('user_initial_score');
|
||||||
|
|
||||||
// chunked
|
// chunked (optionally)
|
||||||
for ($i = 0; $i <= $steps; $i++) {
|
for ($i = 0; $i <= $steps; $i++) {
|
||||||
$start = $i * 250;
|
$start = $i * 250;
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ for ($i = 0; $i <= $steps; $i++) {
|
||||||
$db->insert([
|
$db->insert([
|
||||||
'uid' => $uid,
|
'uid' => $uid,
|
||||||
'player_name' => $row['username'],
|
'player_name' => $row['username'],
|
||||||
'preference' => 'steve',
|
'preference' => $row['preference'],
|
||||||
'last_modified' => Utils::getTimeFormatted()
|
'last_modified' => Utils::getTimeFormatted()
|
||||||
], $v3_players);
|
], $v3_players);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,10 @@ switch ($action) {
|
||||||
View::show('setup.migrations.import-v2-users');
|
View::show('setup.migrations.import-v2-users');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'import-v2-both':
|
||||||
|
View::show('setup.migrations.import-v2-both');
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new App\Exceptions\E('非法参数', 1, true);
|
throw new App\Exceptions\E('非法参数', 1, true);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user