Files
2026-03-03 10:06:12 +08:00

364 lines
11 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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('管理后台已经安装如需重新安装请删除根目录env配置文件并重启');
}
$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('数据库用户名或密码错误');
}
if (stripos($message, 'Connection refused')) {
return $this->fail('Connection refused. 请确认数据库IP端口是否正确数据库已经启动');
}
if (stripos($message, 'timed out')) {
return $this->fail('数据库连接超时请确认数据库IP端口是否正确安全组及防火墙已经放行端口');
}
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('数据库已经安装,请勿重复安装');
}
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('数据库SQL文件不存在');
}
$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('安装成功');
}
/**
* 生成配置文件
*/
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);
}
}