初始化

This commit is contained in:
2026-01-06 12:44:28 +08:00
parent 3f71f87bfa
commit d18044dbd7
186 changed files with 29885 additions and 1 deletions

View File

@@ -0,0 +1,85 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
class Clear extends Command
{
protected function configure()
{
// 指令配置
$this->setName('clear')
->addOption('path', 'd', Option::VALUE_OPTIONAL, 'path to clear', null)
->addOption('cache', 'c', Option::VALUE_NONE, 'clear cache file')
->addOption('log', 'l', Option::VALUE_NONE, 'clear log file')
->addOption('dir', 'r', Option::VALUE_NONE, 'clear empty dir')
->addOption('expire', 'e', Option::VALUE_NONE, 'clear cache file if cache has expired')
->setDescription('Clear runtime file');
}
protected function execute(Input $input, Output $output)
{
$runtimePath = $this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR;
if ($input->getOption('cache')) {
$path = $runtimePath . 'cache';
} elseif ($input->getOption('log')) {
$path = $runtimePath . 'log';
} else {
$path = $input->getOption('path') ?: $runtimePath;
}
$rmdir = $input->getOption('dir') ? true : false;
// --expire 仅当 --cache 时生效
$cache_expire = $input->getOption('expire') && $input->getOption('cache') ? true : false;
$this->clear(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR, $rmdir, $cache_expire);
$output->writeln("<info>Clear Successed</info>");
}
protected function clear(string $path, bool $rmdir, bool $cache_expire): void
{
$files = is_dir($path) ? scandir($path) : [];
foreach ($files as $file) {
if ('.' != $file && '..' != $file && is_dir($path . $file)) {
$this->clear($path . $file . DIRECTORY_SEPARATOR, $rmdir, $cache_expire);
if ($rmdir) {
@rmdir($path . $file);
}
} elseif ('.gitignore' != $file && is_file($path . $file)) {
if ($cache_expire) {
if ($this->cacheHasExpired($path . $file)) {
unlink($path . $file);
}
} else {
unlink($path . $file);
}
}
}
}
/**
* 缓存文件是否已过期
* @param $filename string 文件路径
* @return bool
*/
protected function cacheHasExpired($filename) {
$content = file_get_contents($filename);
$expire = (int) substr($content, 8, 12);
return 0 != $expire && time() - $expire > filemtime($filename);
}
}

View File

@@ -0,0 +1,70 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument as InputArgument;
use think\console\input\Option as InputOption;
use think\console\Output;
class Help extends Command
{
private $command;
/**
* {@inheritdoc}
*/
protected function configure()
{
$this->ignoreValidationErrors();
$this->setName('help')->setDefinition([
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
])->setDescription('Displays help for a command')->setHelp(
<<<EOF
The <info>%command.name%</info> command displays help for a given command:
<info>php %command.full_name% list</info>
To display the list of available commands, please use the <info>list</info> command.
EOF
);
}
/**
* Sets the command.
* @param Command $command The command to set
*/
public function setCommand(Command $command): void
{
$this->command = $command;
}
/**
* {@inheritdoc}
*/
protected function execute(Input $input, Output $output)
{
if (null === $this->command) {
$this->command = $this->getConsole()->find($input->getArgument('command_name'));
}
$output->describe($this->command, [
'raw_text' => $input->getOption('raw'),
]);
$this->command = null;
}
}

View File

@@ -0,0 +1,74 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument as InputArgument;
use think\console\input\Definition as InputDefinition;
use think\console\input\Option as InputOption;
use think\console\Output;
class Lists extends Command
{
/**
* {@inheritdoc}
*/
protected function configure()
{
$this->setName('list')->setDefinition($this->createDefinition())->setDescription('Lists commands')->setHelp(
<<<EOF
The <info>%command.name%</info> command lists all commands:
<info>php %command.full_name%</info>
You can also display the commands for a specific namespace:
<info>php %command.full_name% test</info>
It's also possible to get raw list of commands (useful for embedding command runner):
<info>php %command.full_name% --raw</info>
EOF
);
}
/**
* {@inheritdoc}
*/
public function getNativeDefinition(): InputDefinition
{
return $this->createDefinition();
}
/**
* {@inheritdoc}
*/
protected function execute(Input $input, Output $output)
{
$output->describe($this->getConsole(), [
'raw_text' => $input->getOption('raw'),
'namespace' => $input->getArgument('namespace'),
]);
}
/**
* {@inheritdoc}
*/
private function createDefinition(): InputDefinition
{
return new InputDefinition([
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
]);
}
}

View File

@@ -0,0 +1,99 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 刘志淳 <chun@engineer.com>
// +----------------------------------------------------------------------
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
abstract class Make extends Command
{
protected $type;
abstract protected function getStub();
protected function configure()
{
$this->addArgument('name', Argument::REQUIRED, "The name of the class");
}
protected function execute(Input $input, Output $output)
{
$name = trim($input->getArgument('name'));
$classname = $this->getClassName($name);
$pathname = $this->getPathName($classname);
if (is_file($pathname)) {
$output->writeln('<error>' . $this->type . ':' . $classname . ' already exists!</error>');
return false;
}
if (!is_dir(dirname($pathname))) {
mkdir(dirname($pathname), 0755, true);
}
file_put_contents($pathname, $this->buildClass($classname));
$output->writeln('<info>' . $this->type . ':' . $classname . ' created successfully.</info>');
}
protected function buildClass(string $name)
{
$stub = file_get_contents($this->getStub());
$namespace = trim(implode('\\', array_slice(explode('\\', $name), 0, -1)), '\\');
$class = str_replace($namespace . '\\', '', $name);
return str_replace(['{%className%}', '{%actionSuffix%}', '{%namespace%}', '{%app_namespace%}'], [
$class,
$this->app->config->get('route.action_suffix'),
$namespace,
$this->app->getNamespace(),
], $stub);
}
protected function getPathName(string $name): string
{
$name = substr($name, 4);
return $this->app->getBasePath() . ltrim(str_replace('\\', '/', $name), '/') . '.php';
}
protected function getClassName(string $name): string
{
if (str_contains($name, '\\')) {
return $name;
}
if (str_contains($name, '@')) {
[$app, $name] = explode('@', $name);
} else {
$app = '';
}
if (str_contains($name, '/')) {
$name = str_replace('/', '\\', $name);
}
return $this->getNamespace($app) . '\\' . $name;
}
protected function getNamespace(string $app): string
{
return 'app' . ($app ? '\\' . $app : '');
}
}

View File

@@ -0,0 +1,141 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console\command;
use DirectoryIterator;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\console\Table;
use think\event\RouteLoaded;
class RouteList extends Command
{
protected $sortBy = [
'rule' => 0,
'route' => 1,
'method' => 2,
'name' => 3,
'domain' => 4,
];
protected function configure()
{
$this->setName('route:list')
->addArgument('style', Argument::OPTIONAL, "the style of the table.", 'default')
->addOption('sort', 's', Option::VALUE_OPTIONAL, 'order by rule name.', 0)
->addOption('more', 'm', Option::VALUE_NONE, 'show route options.')
->setDescription('show route list.');
}
protected function execute(Input $input, Output $output)
{
$filename = $this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . 'route_list.php';
if (is_file($filename)) {
unlink($filename);
} elseif (!is_dir(dirname($filename))) {
mkdir(dirname($filename), 0755);
}
$content = $this->getRouteList();
file_put_contents($filename, 'Route List' . PHP_EOL . $content);
}
protected function scanRoute($path, $root, $autoGroup)
{
$iterator = new DirectoryIterator($path);
foreach ($iterator as $fileinfo) {
if ($fileinfo->isDot()) {
continue;
}
if ($fileinfo->getType() == 'file' && $fileinfo->getExtension() == 'php') {
$groupName = str_replace('\\', '/', substr_replace($fileinfo->getPath(), '', 0, strlen($root)));
if ($groupName) {
$this->app->route->group($groupName, function() use ($fileinfo) {
include $fileinfo->getRealPath();
});
} else {
include $fileinfo->getRealPath();
}
} elseif ($autoGroup && $fileinfo->isDir()) {
$this->scanRoute($fileinfo->getPathname(), $root, $autoGroup);
}
}
}
protected function getRouteList(?string $dir = null): string
{
$this->app->route->clear();
$this->app->route->lazy(false);
$autoGroup = $this->app->route->config('route_auto_group');
$path = $this->app->getRootPath() . 'route' . DIRECTORY_SEPARATOR;
$this->scanRoute($path, $path, $autoGroup);
//触发路由载入完成事件
$this->app->event->trigger(RouteLoaded::class);
$table = new Table();
if ($this->input->hasOption('more')) {
$header = ['Rule', 'Route', 'Method', 'Name', 'Domain', 'Option', 'Pattern'];
} else {
$header = ['Rule', 'Route', 'Method', 'Name'];
}
$table->setHeader($header);
$routeList = $this->app->route->getRuleList();
$rows = [];
foreach ($routeList as $item) {
if (is_array($item['route'])) {
$item['route'] = '[' . $item['route'][0] .' , ' . $item['route'][1] . ']';
} else {
$item['route'] = $item['route'] instanceof \Closure ? '<Closure>' : $item['route'];
}
$row = [$item['rule'], $item['route'], $item['method'], $item['name']];
if ($this->input->hasOption('more')) {
array_push($row, $item['domain'], json_encode($item['option']), json_encode($item['pattern']));
}
$rows[] = $row;
}
if ($this->input->getOption('sort')) {
$sort = strtolower($this->input->getOption('sort'));
if (isset($this->sortBy[$sort])) {
$sort = $this->sortBy[$sort];
}
uasort($rows, function ($a, $b) use ($sort) {
$itemA = $a[$sort] ?? null;
$itemB = $b[$sort] ?? null;
return strcasecmp($itemA, $itemB);
});
}
$table->setRows($rows);
if ($this->input->getArgument('style')) {
$style = $this->input->getArgument('style');
$table->setStyle($style);
}
return $this->table($table);
}
}

View File

@@ -0,0 +1,72 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Slince <taosikai@yeah.net>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
class RunServer extends Command
{
public function configure()
{
$this->setName('run')
->addOption(
'host',
'H',
Option::VALUE_OPTIONAL,
'The host to server the application on',
'0.0.0.0'
)
->addOption(
'port',
'p',
Option::VALUE_OPTIONAL,
'The port to server the application on',
8000
)
->addOption(
'root',
'r',
Option::VALUE_OPTIONAL,
'The document root of the application',
''
)
->setDescription('PHP Built-in Server for ThinkPHP');
}
public function execute(Input $input, Output $output)
{
$host = $input->getOption('host');
$port = $input->getOption('port');
$root = $input->getOption('root');
if (empty($root)) {
$root = $this->app->getRootPath() . 'public';
}
$command = sprintf(
'"%s" -S %s:%d -t %s %s',
PHP_BINARY,
$host,
$port,
escapeshellarg($root),
escapeshellarg($root . DIRECTORY_SEPARATOR . 'router.php')
);
$output->writeln(sprintf('ThinkPHP Development server is started On <http://%s:%s/>', $host, $port));
$output->writeln(sprintf('You can exit with <info>`CTRL-C`</info>'));
$output->writeln(sprintf('Document root is: %s', $root));
passthru($command);
}
}

View File

@@ -0,0 +1,52 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace think\console\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
class ServiceDiscover extends Command
{
public function configure()
{
$this->setName('service:discover')
->setDescription('Discover Services for ThinkPHP');
}
public function execute(Input $input, Output $output)
{
if (is_file($path = $this->app->getRootPath() . 'vendor/composer/installed.json')) {
$packages = json_decode(@file_get_contents($path), true);
// Compatibility with Composer 2.0
if (isset($packages['packages'])) {
$packages = $packages['packages'];
}
$services = [];
foreach ($packages as $package) {
if (!empty($package['extra']['think']['services'])) {
$services = array_merge($services, (array) $package['extra']['think']['services']);
}
}
$header = '// This file is automatically generated at:' . date('Y-m-d H:i:s') . PHP_EOL . 'declare (strict_types = 1);' . PHP_EOL;
$content = '<?php ' . PHP_EOL . $header . "return " . var_export($services, true) . ';';
file_put_contents($this->app->getRootPath() . 'vendor/services.php', $content);
$output->writeln('<info>Succeed!</info>');
}
}
}

View File

@@ -0,0 +1,69 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
declare(strict_types=1);
namespace think\console\command;
use think\console\Command;
use think\console\input\Option;
class VendorPublish extends Command
{
public function configure()
{
$this->setName('vendor:publish')
->addOption('force', 'f', Option::VALUE_NONE, 'Overwrite any existing files')
->setDescription('Publish any publishable assets from vendor packages');
}
public function handle()
{
$force = $this->input->getOption('force');
if (is_file($path = $this->app->getRootPath() . 'vendor/composer/installed.json')) {
$packages = json_decode(@file_get_contents($path), true);
// Compatibility with Composer 2.0
if (isset($packages['packages'])) {
$packages = $packages['packages'];
}
foreach ($packages as $package) {
//配置
$configDir = $this->app->getConfigPath();
if (!empty($package['extra']['think']['config'])) {
$installPath = $this->app->getRootPath() . 'vendor/' . $package['name'] . DIRECTORY_SEPARATOR;
foreach ((array) $package['extra']['think']['config'] as $name => $file) {
$target = $configDir . $name . '.php';
$source = $installPath . $file;
if (is_file($target) && !$force) {
$this->output->info("File {$target} exist!");
continue;
}
if (!is_file($source)) {
$this->output->info("File {$source} not exist!");
continue;
}
copy($source, $target);
}
}
}
$this->output->writeln('<info>Succeed!</info>');
}
}
}

View File

@@ -0,0 +1,35 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace think\console\command;
use Composer\InstalledVersions;
use think\console\Command;
use think\console\Input;
use think\console\Output;
class Version extends Command
{
protected function configure()
{
// 指令配置
$this->setName('version')
->setDescription('show thinkphp framework version');
}
protected function execute(Input $input, Output $output)
{
$version = InstalledVersions::getPrettyVersion('topthink/framework');
$output->writeln($version);
}
}

View File

@@ -0,0 +1,54 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command\make;
use think\console\command\Make;
use think\console\input\Argument;
class Command extends Make
{
protected $type = "Command";
protected function configure()
{
parent::configure();
$this->setName('make:command')
->addArgument('commandName', Argument::OPTIONAL, "The name of the command")
->setDescription('Create a new command class');
}
protected function buildClass(string $name): string
{
$commandName = $this->input->getArgument('commandName') ?: strtolower(basename($name));
$namespace = trim(implode('\\', array_slice(explode('\\', $name), 0, -1)), '\\');
$class = str_replace($namespace . '\\', '', $name);
$stub = file_get_contents($this->getStub());
return str_replace(['{%commandName%}', '{%className%}', '{%namespace%}', '{%app_namespace%}'], [
$commandName,
$class,
$namespace,
$this->app->getNamespace(),
], $stub);
}
protected function getStub(): string
{
return __DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'command.stub';
}
protected function getNamespace(string $app): string
{
return parent::getNamespace($app) . '\\command';
}
}

View File

@@ -0,0 +1,55 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command\make;
use think\console\command\Make;
use think\console\input\Option;
class Controller extends Make
{
protected $type = "Controller";
protected function configure()
{
parent::configure();
$this->setName('make:controller')
->addOption('api', null, Option::VALUE_NONE, 'Generate an api controller class.')
->addOption('plain', null, Option::VALUE_NONE, 'Generate an empty controller class.')
->setDescription('Create a new resource controller class');
}
protected function getStub(): string
{
$stubPath = __DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR;
if ($this->input->getOption('api')) {
return $stubPath . 'controller.api.stub';
}
if ($this->input->getOption('plain')) {
return $stubPath . 'controller.plain.stub';
}
return $stubPath . 'controller.stub';
}
protected function getClassName(string $name): string
{
return parent::getClassName($name) . ($this->app->config->get('route.controller_suffix') ? 'Controller' : '');
}
protected function getNamespace(string $app): string
{
return parent::getNamespace($app) . '\\controller';
}
}

View File

@@ -0,0 +1,35 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command\make;
use think\console\command\Make;
class Event extends Make
{
protected $type = "Event";
protected function configure()
{
parent::configure();
$this->setName('make:event')
->setDescription('Create a new event class');
}
protected function getStub(): string
{
return __DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'event.stub';
}
protected function getNamespace(string $app): string
{
return parent::getNamespace($app) . '\\event';
}
}

View File

@@ -0,0 +1,35 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command\make;
use think\console\command\Make;
class Listener extends Make
{
protected $type = "Listener";
protected function configure()
{
parent::configure();
$this->setName('make:listener')
->setDescription('Create a new listener class');
}
protected function getStub(): string
{
return __DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'listener.stub';
}
protected function getNamespace(string $app): string
{
return parent::getNamespace($app) . '\\listener';
}
}

View File

@@ -0,0 +1,36 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command\make;
use think\console\command\Make;
class Middleware extends Make
{
protected $type = "Middleware";
protected function configure()
{
parent::configure();
$this->setName('make:middleware')
->setDescription('Create a new middleware class');
}
protected function getStub(): string
{
return __DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'middleware.stub';
}
protected function getNamespace(string $app): string
{
return parent::getNamespace($app) . '\\middleware';
}
}

View File

@@ -0,0 +1,36 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command\make;
use think\console\command\Make;
class Model extends Make
{
protected $type = "Model";
protected function configure()
{
parent::configure();
$this->setName('make:model')
->setDescription('Create a new model class');
}
protected function getStub(): string
{
return __DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'model.stub';
}
protected function getNamespace(string $app): string
{
return parent::getNamespace($app) . '\\model';
}
}

View File

@@ -0,0 +1,36 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command\make;
use think\console\command\Make;
class Service extends Make
{
protected $type = "Service";
protected function configure()
{
parent::configure();
$this->setName('make:service')
->setDescription('Create a new Service class');
}
protected function getStub(): string
{
return __DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'service.stub';
}
protected function getNamespace(string $app): string
{
return parent::getNamespace($app) . '\\service';
}
}

View File

@@ -0,0 +1,35 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command\make;
use think\console\command\Make;
class Subscribe extends Make
{
protected $type = "Subscribe";
protected function configure()
{
parent::configure();
$this->setName('make:subscribe')
->setDescription('Create a new subscribe class');
}
protected function getStub(): string
{
return __DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR . 'subscribe.stub';
}
protected function getNamespace(string $app): string
{
return parent::getNamespace($app) . '\\subscribe';
}
}

View File

@@ -0,0 +1,38 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command\make;
use think\console\command\Make;
class Validate extends Make
{
protected $type = "Validate";
protected function configure()
{
parent::configure();
$this->setName('make:validate')
->setDescription('Create a validate class');
}
protected function getStub(): string
{
$stubPath = __DIR__ . DIRECTORY_SEPARATOR . 'stubs' . DIRECTORY_SEPARATOR;
return $stubPath . 'validate.stub';
}
protected function getNamespace(string $app): string
{
return parent::getNamespace($app) . '\\validate';
}
}

View File

@@ -0,0 +1,26 @@
<?php
declare (strict_types = 1);
namespace {%namespace%};
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
class {%className%} extends Command
{
protected function configure()
{
// 指令配置
$this->setName('{%commandName%}')
->setDescription('the {%commandName%} command');
}
protected function execute(Input $input, Output $output)
{
// 指令输出
$output->writeln('{%commandName%}');
}
}

View File

@@ -0,0 +1,64 @@
<?php
declare (strict_types = 1);
namespace {%namespace%};
use think\Request;
class {%className%}
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index{%actionSuffix%}()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save{%actionSuffix%}(Request $request)
{
//
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read{%actionSuffix%}($id)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update{%actionSuffix%}(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete{%actionSuffix%}($id)
{
//
}
}

View File

@@ -0,0 +1,9 @@
<?php
declare (strict_types = 1);
namespace {%namespace%};
class {%className%}
{
//
}

View File

@@ -0,0 +1,85 @@
<?php
declare (strict_types = 1);
namespace {%namespace%};
use think\Request;
class {%className%}
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index{%actionSuffix%}()
{
//
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create{%actionSuffix%}()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save{%actionSuffix%}(Request $request)
{
//
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read{%actionSuffix%}($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit{%actionSuffix%}($id)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update{%actionSuffix%}(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete{%actionSuffix%}($id)
{
//
}
}

View File

@@ -0,0 +1,8 @@
<?php
declare (strict_types = 1);
namespace {%namespace%};
class {%className%}
{
}

View File

@@ -0,0 +1,17 @@
<?php
declare (strict_types = 1);
namespace {%namespace%};
class {%className%}
{
/**
* 事件监听处理
*
* @return mixed
*/
public function handle($event)
{
//
}
}

View File

@@ -0,0 +1,19 @@
<?php
declare (strict_types = 1);
namespace {%namespace%};
class {%className%}
{
/**
* 处理请求
*
* @param \think\Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
//
}
}

View File

@@ -0,0 +1,14 @@
<?php
declare (strict_types = 1);
namespace {%namespace%};
use think\Model;
/**
* @mixin \think\Model
*/
class {%className%} extends Model
{
//
}

View File

@@ -0,0 +1,27 @@
<?php
declare (strict_types = 1);
namespace {%namespace%};
class {%className%} extends \think\Service
{
/**
* 注册服务
*
* @return mixed
*/
public function register()
{
//
}
/**
* 执行服务
*
* @return mixed
*/
public function boot()
{
//
}
}

View File

@@ -0,0 +1,8 @@
<?php
declare (strict_types = 1);
namespace {%namespace%};
class {%className%}
{
}

View File

@@ -0,0 +1,25 @@
<?php
declare (strict_types = 1);
namespace {%namespace%};
use think\Validate;
class {%className%} extends Validate
{
/**
* 定义验证规则
* 格式:'字段名' => ['规则1','规则2'...]
*
* @var array
*/
protected $rule = [];
/**
* 定义错误信息
* 格式:'字段名.规则名' => '错误信息'
*
* @var array
*/
protected $message = [];
}

View File

@@ -0,0 +1,64 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\console\command\optimize;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
class Config extends Command
{
protected function configure()
{
$this->setName('optimize:config')
->addArgument('dir', Argument::OPTIONAL, 'dir name .')
->setDescription('Build config cache.');
}
protected function execute(Input $input, Output $output)
{
// 加载配置文件
$dir = $input->getArgument('dir') ?: '';
$path = $this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . ($dir ? $dir . DIRECTORY_SEPARATOR : '');
if (!is_dir($path)) {
try {
mkdir($path, 0755, true);
} catch (\Exception $e) {
// 创建失败
}
}
$file = $path . 'config.php';
$config = $this->loadConfig($dir);
$content = '<?php ' . PHP_EOL . 'return ' . var_export($config, true) . ';';
if (file_put_contents($file, $content)) {
$output->writeln("<info>Succeed!</info>");
} else {
$output->writeln("<error>config build fail</error>");
}
}
public function loadConfig($dir = '')
{
$configPath = $this->app->getRootPath() . ($dir ? 'app' . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR : '') . 'config' . DIRECTORY_SEPARATOR;
$files = [];
if (is_dir($configPath)) {
$files = glob($configPath . '*' . $this->app->getConfigExt());
}
foreach ($files as $file) {
$this->app->config->load($file, pathinfo($file, PATHINFO_FILENAME));
}
return $this->app->config->get();
}
}

View File

@@ -0,0 +1,86 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console\command\optimize;
use DirectoryIterator;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use think\event\RouteLoaded;
class Route extends Command
{
protected function configure()
{
$this->setName('optimize:route')
->addArgument('dir', Argument::OPTIONAL, 'dir name .')
->setDescription('Build app route cache.');
}
protected function execute(Input $input, Output $output)
{
$dir = $input->getArgument('dir') ?: '';
$path = $this->app->getRootPath() . 'runtime' . DIRECTORY_SEPARATOR . ($dir ? $dir . DIRECTORY_SEPARATOR : '');
if (!is_dir($path)) {
try {
mkdir($path, 0755, true);
} catch (\Exception $e) {
// 创建失败
}
}
file_put_contents($path . 'route.php', $this->buildRouteCache($dir));
$output->writeln('<info>Succeed!</info>');
}
protected function scanRoute($path, $root, $autoGroup)
{
$iterator = new DirectoryIterator($path);
foreach ($iterator as $fileinfo) {
if ($fileinfo->isDot()) {
continue;
}
if ($fileinfo->getType() == 'file' && $fileinfo->getExtension() == 'php') {
$groupName = str_replace('\\', '/', substr_replace($fileinfo->getPath(), '', 0, strlen($root)));
if ($groupName) {
$this->app->route->group($groupName, function() use ($fileinfo) {
include $fileinfo->getRealPath();
});
} else {
include $fileinfo->getRealPath();
}
} elseif ($autoGroup && $fileinfo->isDir()) {
$this->scanRoute($fileinfo->getPathname(), $root, $autoGroup);
}
}
}
protected function buildRouteCache(?string $dir = null): string
{
$this->app->route->clear();
$this->app->route->lazy(false);
// 路由检测
$autoGroup = $this->app->route->config('route_auto_group');
$path = $this->app->getRootPath() . ($dir ? 'app' . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR : '') . 'route' . DIRECTORY_SEPARATOR;
$this->scanRoute($path, $path, $autoGroup);
//触发路由载入完成事件
$this->app->event->trigger(RouteLoaded::class);
$rules = $this->app->route->getName();
return '<?php ' . PHP_EOL . 'return ' . var_export($rules, true) . ';';
}
}

View File

@@ -0,0 +1,109 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think\console\command\optimize;
use Exception;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\db\PDOConnection;
class Schema extends Command
{
protected function configure()
{
$this->setName('optimize:schema')
->addArgument('dir', Argument::OPTIONAL, 'dir name .')
->addOption('connection', null, Option::VALUE_REQUIRED, 'connection name .')
->addOption('table', null, Option::VALUE_REQUIRED, 'table name .')
->setDescription('Build database schema cache.');
}
protected function execute(Input $input, Output $output)
{
$dir = $input->getArgument('dir') ?: '';
if ($input->hasOption('table')) {
$connection = $this->app->db->connect($input->getOption('connection'));
if (!$connection instanceof PDOConnection) {
$output->error("only PDO connection support schema cache!");
return;
}
$table = $input->getOption('table');
if (!str_contains($table, '.')) {
$dbName = $connection->getConfig('database');
} else {
[$dbName, $table] = explode('.', $table);
}
if ($table == '*') {
$table = $connection->getTables($dbName);
}
$this->buildDataBaseSchema($connection, (array) $table, $dbName);
} else {
if ($dir) {
$appPath = $this->app->getBasePath() . $dir . DIRECTORY_SEPARATOR;
$namespace = 'app\\' . $dir;
} else {
$appPath = $this->app->getBasePath();
$namespace = 'app';
}
$path = $appPath . 'model';
$list = is_dir($path) ? scandir($path) : [];
foreach ($list as $file) {
if (str_starts_with($file, '.')) {
continue;
}
$class = '\\' . $namespace . '\\model\\' . pathinfo($file, PATHINFO_FILENAME);
if (!class_exists($class)) {
continue;
}
$this->buildModelSchema($class);
}
}
$output->writeln('<info>Succeed!</info>');
}
protected function buildModelSchema(string $class): void
{
$reflect = new \ReflectionClass($class);
if (!$reflect->isAbstract() && $reflect->isSubclassOf('\think\Model')) {
try {
/** @var \think\Model $model */
$model = new $class;
$connection = $model->db()->getConnection();
if ($connection instanceof PDOConnection) {
$table = $model->getTable();
//预读字段信息
$connection->getSchemaInfo($table, true);
}
} catch (Exception $e) {
}
}
}
protected function buildDataBaseSchema(PDOConnection $connection, array $tables, string $dbName): void
{
foreach ($tables as $table) {
//预读字段信息
$connection->getSchemaInfo("{$dbName}.{$table}", true);
}
}
}