364 lines
11 KiB
PHP
364 lines
11 KiB
PHP
<?php
|
||
// +----------------------------------------------------------------------
|
||
// | saiadmin [ saiadmin快速开发框架 ]
|
||
// +----------------------------------------------------------------------
|
||
// | Author: sai <1430792918@qq.com>
|
||
// +----------------------------------------------------------------------
|
||
namespace plugin\saiadmin\app\controller;
|
||
|
||
use Throwable;
|
||
use support\Request;
|
||
use support\Response;
|
||
use plugin\saiadmin\exception\ApiException;
|
||
use plugin\saiadmin\basic\OpenController;
|
||
|
||
/**
|
||
* 安装控制器
|
||
*/
|
||
class InstallController extends OpenController
|
||
{
|
||
/**
|
||
* 不需要登录的方法
|
||
*/
|
||
protected array $noNeedLogin = ['index', 'install'];
|
||
|
||
/**
|
||
* 应用名称
|
||
* @var string
|
||
*/
|
||
protected string $app = 'saiadmin';
|
||
|
||
protected string $version = '6.0.0';
|
||
|
||
/**
|
||
* 安装首页
|
||
*/
|
||
public function index()
|
||
{
|
||
$data['app'] = $this->app;
|
||
$data['version'] = config('plugin.saiadmin.app.version', $this->version);
|
||
|
||
$env = base_path() . DIRECTORY_SEPARATOR . '.env';
|
||
|
||
clearstatcache();
|
||
if (is_file($env)) {
|
||
$data['error'] = '程序已经安装';
|
||
return view('install/error', $data);
|
||
}
|
||
|
||
if (!is_writable(base_path() . DIRECTORY_SEPARATOR . 'config')) {
|
||
$data['error'] = '权限认证失败';
|
||
return view('install/error', $data);
|
||
}
|
||
|
||
return view('install/index', $data);
|
||
}
|
||
|
||
/**
|
||
* 执行安装
|
||
*/
|
||
public function install(Request $request)
|
||
{
|
||
$env = base_path() . DIRECTORY_SEPARATOR . '.env';
|
||
|
||
clearstatcache();
|
||
if (is_file($env)) {
|
||
return $this->fail('admin already installed, to reinstall please delete env file and restart');
|
||
}
|
||
|
||
$user = $request->post('username');
|
||
$password = $request->post('password');
|
||
$database = $request->post('database');
|
||
$host = $request->post('host');
|
||
$port = (int) $request->post('port') ?: 3306;
|
||
$dataType = $request->post('dataType', 'demo');
|
||
|
||
try {
|
||
$db = $this->getPdo($host, $user, $password, $port);
|
||
$smt = $db->query("show databases like '$database'");
|
||
if (empty($smt->fetchAll())) {
|
||
$db->exec("create database `$database` CHARSET utf8mb4 COLLATE utf8mb4_general_ci");
|
||
}
|
||
} catch (\Throwable $e) {
|
||
$message = $e->getMessage();
|
||
if (stripos($message, 'Access denied for user')) {
|
||
return $this->fail('database username or password is incorrect');
|
||
}
|
||
if (stripos($message, 'Connection refused')) {
|
||
return $this->fail('connection refused, please check database ip/port and ensure database is running');
|
||
}
|
||
if (stripos($message, 'timed out')) {
|
||
return $this->fail('database connection timeout, please check ip/port and firewall/security group rules');
|
||
}
|
||
throw $e;
|
||
}
|
||
|
||
$db->exec("use `$database`");
|
||
|
||
$smt = $db->query("show tables like 'sa_system_menu';");
|
||
$tables = $smt->fetchAll();
|
||
if (count($tables) > 0) {
|
||
return $this->fail('database already installed, please do not install again');
|
||
}
|
||
|
||
if ($dataType == 'demo') {
|
||
$sql_file = base_path() . '/plugin/saiadmin/db/saiadmin-6.0.sql';
|
||
} else {
|
||
$sql_file = base_path() . '/plugin/saiadmin/db/saiadmin-pure.sql';
|
||
}
|
||
|
||
if (!is_file($sql_file)) {
|
||
return $this->fail('database SQL file not found');
|
||
}
|
||
|
||
$sql_query = file_get_contents($sql_file);
|
||
|
||
$db->exec($sql_query);
|
||
|
||
$this->generateConfig();
|
||
|
||
$env_config = <<<EOF
|
||
# 数据库配置
|
||
DB_TYPE = mysql
|
||
DB_HOST = $host
|
||
DB_PORT = $port
|
||
DB_NAME = $database
|
||
DB_USER = $user
|
||
DB_PASSWORD = $password
|
||
DB_PREFIX =
|
||
|
||
# 缓存方式
|
||
CACHE_MODE = file
|
||
|
||
# Redis配置
|
||
REDIS_HOST = 127.0.0.1
|
||
REDIS_PORT = 6379
|
||
REDIS_PASSWORD = ''
|
||
REDIS_DB = 0
|
||
|
||
# 验证码配置
|
||
CAPTCHA_MODE = cache
|
||
|
||
#前端目录
|
||
FRONTEND_DIR = saiadmin-artd
|
||
EOF;
|
||
file_put_contents(base_path() . DIRECTORY_SEPARATOR . '.env', $env_config);
|
||
|
||
// 尝试reload
|
||
if (function_exists('posix_kill')) {
|
||
set_error_handler(function () {});
|
||
posix_kill(posix_getppid(), SIGUSR1);
|
||
restore_error_handler();
|
||
}
|
||
|
||
return $this->success('install success');
|
||
}
|
||
|
||
/**
|
||
* 生成配置文件
|
||
*/
|
||
protected function generateConfig()
|
||
{
|
||
// 1、think-orm配置文件
|
||
$think_orm_config = <<<EOF
|
||
<?php
|
||
|
||
return [
|
||
'default' => 'mysql',
|
||
'connections' => [
|
||
'mysql' => [
|
||
// 数据库类型
|
||
'type' => env('DB_TYPE', 'mysql'),
|
||
// 服务器地址
|
||
'hostname' => env('DB_HOST', '127.0.0.1'),
|
||
// 数据库名
|
||
'database' => env('DB_NAME', 'saiadmin'),
|
||
// 数据库用户名
|
||
'username' => env('DB_USER', 'root'),
|
||
// 数据库密码
|
||
'password' => env('DB_PASSWORD', '123456'),
|
||
// 数据库连接端口
|
||
'hostport' => env('DB_PORT', 3306),
|
||
// 数据库连接参数
|
||
'params' => [
|
||
// 连接超时3秒
|
||
\PDO::ATTR_TIMEOUT => 3,
|
||
],
|
||
// 数据库编码默认采用utf8
|
||
'charset' => 'utf8',
|
||
// 数据库表前缀
|
||
'prefix' => env('DB_PREFIX', ''),
|
||
// 断线重连
|
||
'break_reconnect' => true,
|
||
// 自定义分页类
|
||
'bootstrap' => '',
|
||
// 连接池配置
|
||
'pool' => [
|
||
'max_connections' => 5, // 最大连接数
|
||
'min_connections' => 1, // 最小连接数
|
||
'wait_timeout' => 3, // 从连接池获取连接等待超时时间
|
||
'idle_timeout' => 60, // 连接最大空闲时间,超过该时间会被回收
|
||
'heartbeat_interval' => 50, // 心跳检测间隔,需要小于60秒
|
||
],
|
||
],
|
||
],
|
||
];
|
||
EOF;
|
||
file_put_contents(base_path() . '/config/think-orm.php', $think_orm_config);
|
||
|
||
// 2、chache配置文件
|
||
$cache_config = <<<EOF
|
||
<?php
|
||
|
||
return [
|
||
'default' => env('CACHE_MODE', 'file'),
|
||
'stores' => [
|
||
'file' => [
|
||
'driver' => 'file',
|
||
'path' => runtime_path('cache')
|
||
],
|
||
'redis' => [
|
||
'driver' => 'redis',
|
||
'connection' => 'default'
|
||
],
|
||
'array' => [
|
||
'driver' => 'array'
|
||
]
|
||
]
|
||
];
|
||
EOF;
|
||
file_put_contents(base_path() . '/config/cache.php', $cache_config);
|
||
|
||
// 3、redis配置文件
|
||
$redis_config = <<<EOF
|
||
<?php
|
||
|
||
return [
|
||
'default' => [
|
||
'password' => env('REDIS_PASSWORD', ''),
|
||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||
'port' => env('REDIS_PORT', 6379),
|
||
'database' => env('REDIS_DB', 0),
|
||
'pool' => [
|
||
'max_connections' => 5,
|
||
'min_connections' => 1,
|
||
'wait_timeout' => 3,
|
||
'idle_timeout' => 60,
|
||
'heartbeat_interval' => 50,
|
||
],
|
||
]
|
||
];
|
||
EOF;
|
||
file_put_contents(base_path() . '/config/redis.php', $redis_config);
|
||
|
||
// 4、think-cache配置文件
|
||
$think_cache_config = <<<EOF
|
||
<?php
|
||
return [
|
||
// 默认缓存驱动
|
||
'default' => env('CACHE_MODE', 'file'),
|
||
// 缓存连接方式配置
|
||
'stores' => [
|
||
// redis缓存
|
||
'redis' => [
|
||
// 驱动方式
|
||
'type' => 'redis',
|
||
// 服务器地址
|
||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||
// 服务器端口
|
||
'port' => env('REDIS_PORT', 6379),
|
||
// 服务器密码
|
||
'password' => env('REDIS_PASSWORD', ''),
|
||
// 数据库
|
||
'select' => env('REDIS_DB', 0),
|
||
// 缓存前缀
|
||
'prefix' => 'cache:',
|
||
// 默认缓存有效期 0表示永久缓存
|
||
'expire' => 0,
|
||
// Thinkphp官方没有这个参数,由于生成的tag键默认不过期,如果tag键数量很大,避免长时间占用内存,可以设置一个超过其他缓存的过期时间,0为不设置
|
||
'tag_expire' => 86400 * 30,
|
||
// 缓存标签前缀
|
||
'tag_prefix' => 'tag:',
|
||
// 连接池配置
|
||
'pool' => [
|
||
'max_connections' => 5, // 最大连接数
|
||
'min_connections' => 1, // 最小连接数
|
||
'wait_timeout' => 3, // 从连接池获取连接等待超时时间
|
||
'idle_timeout' => 60, // 连接最大空闲时间,超过该时间会被回收
|
||
'heartbeat_interval' => 50, // 心跳检测间隔,需要小于60秒
|
||
],
|
||
],
|
||
// 文件缓存
|
||
'file' => [
|
||
// 驱动方式
|
||
'type' => 'file',
|
||
// 设置不同的缓存保存目录
|
||
'path' => runtime_path() . '/file/',
|
||
],
|
||
],
|
||
];
|
||
EOF;
|
||
file_put_contents(base_path() . '/config/think-cache.php', $think_cache_config);
|
||
|
||
// 5、database配置文件
|
||
$database = <<<EOF
|
||
<?php
|
||
return [
|
||
'default' => 'mysql',
|
||
'connections' => [
|
||
'mysql' => [
|
||
'driver' => env('DB_TYPE', 'mysql'),
|
||
'host' => env('DB_HOST', '127.0.0.1'),
|
||
'port' => env('DB_PORT', 3306),
|
||
'database' => env('DB_NAME', 'saiadmin'),
|
||
'username' => env('DB_USER', 'root'),
|
||
'password' => env('DB_PASSWORD', '123456'),
|
||
'charset' => env('DB_CHARSET', 'utf8mb4'),
|
||
'collation' => env('DB_COLLATION', 'utf8mb4_general_ci'),
|
||
'prefix' => env('DB_PREFIX', ''),
|
||
'strict' => true,
|
||
'engine' => null,
|
||
'options' => [
|
||
PDO::ATTR_EMULATE_PREPARES => false, // Must be false for Swoole and Swow drivers.
|
||
],
|
||
'pool' => [
|
||
'max_connections' => 5,
|
||
'min_connections' => 1,
|
||
'wait_timeout' => 3,
|
||
'idle_timeout' => 60,
|
||
'heartbeat_interval' => 50,
|
||
],
|
||
],
|
||
],
|
||
];
|
||
EOF;
|
||
file_put_contents(base_path() . '/config/database.php', $database);
|
||
|
||
}
|
||
|
||
/**
|
||
* 获取pdo连接
|
||
* @param $host
|
||
* @param $username
|
||
* @param $password
|
||
* @param $port
|
||
* @param $database
|
||
* @return \PDO
|
||
*/
|
||
protected function getPdo($host, $username, $password, $port, $database = null): \PDO
|
||
{
|
||
$dsn = "mysql:host=$host;port=$port;";
|
||
if ($database) {
|
||
$dsn .= "dbname=$database";
|
||
}
|
||
$params = [
|
||
\PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8mb4",
|
||
\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
|
||
\PDO::ATTR_EMULATE_PREPARES => false,
|
||
\PDO::ATTR_TIMEOUT => 5,
|
||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
||
];
|
||
return new \PDO($dsn, $username, $password, $params);
|
||
}
|
||
}
|