first commit
This commit is contained in:
commit
a6cbb3e720
6
.dockerignore
Normal file
6
.dockerignore
Normal file
@ -0,0 +1,6 @@
|
||||
/.git
|
||||
/.idea
|
||||
/.vscode
|
||||
/runtime/**
|
||||
!/runtime/.gitignore
|
||||
/vendor
|
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/.idea
|
||||
/.vscode
|
||||
/vendor
|
||||
*.log
|
||||
.env
|
||||
/tests/tmp
|
||||
/tests/.phpunit.result.cache
|
32
Dockerfile
Normal file
32
Dockerfile
Normal file
@ -0,0 +1,32 @@
|
||||
# 用于将项目构建成镜像
|
||||
ARG WEBMAN_DOCKER_VERSION=8.1-cli-alpine
|
||||
|
||||
# https://github.com/krissss/docker-webman
|
||||
FROM krisss/docker-webman:$WEBMAN_DOCKER_VERSION
|
||||
|
||||
# 增加额外的扩展
|
||||
#RUN apk add --no-cache git
|
||||
#RUN install-php-extensions imagick
|
||||
|
||||
# 设置配置文件
|
||||
# 自定义 php 配置文件,如果需要的话
|
||||
# 覆盖镜像自带的
|
||||
#COPY environments/docker/php.ini "$PHP_INI_DIR/conf.d/app.ini"
|
||||
# 扩展额外的
|
||||
#COPY environments/docker/my_php.ini "$PHP_INI_DIR/conf.d/my_php.ini"
|
||||
# 自定义 supervisor 配置,如果需要的话
|
||||
# 覆盖镜像自带的
|
||||
#COPY environments/docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
# 扩展额外的
|
||||
#COPY environments/docker/my_supervisord.conf /etc/supervisor/conf.d/my_supervisord.conf
|
||||
|
||||
# 预先加载 Composer 包依赖,优化 Docker 构建镜像的速度
|
||||
COPY ./composer.json /app/
|
||||
COPY ./composer.lock /app/
|
||||
RUN composer install --no-interaction --no-dev --no-autoloader --no-scripts
|
||||
|
||||
# 复制项目代码
|
||||
COPY . /app
|
||||
|
||||
# 执行 Composer 自动加载和相关脚本
|
||||
RUN composer install --no-interaction --no-dev && composer dump-autoload
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 walkor<walkor@workerman.net> and contributors (see https://github.com/walkor/webman/contributors)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
10
app/common/model/FictionLibraryModel.php
Normal file
10
app/common/model/FictionLibraryModel.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
class FictionLibraryModel extends Model
|
||||
{
|
||||
protected $table = 'fiction_library';
|
||||
}
|
21
app/common/repository/FictionLibraryRepository.php
Normal file
21
app/common/repository/FictionLibraryRepository.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\repository;
|
||||
|
||||
use app\common\model\FictionLibraryModel;
|
||||
|
||||
class FictionLibraryRepository extends FictionLibraryModel
|
||||
{
|
||||
public function selectAll(array $fields, int $page, int $limit, string $keyword):array
|
||||
{
|
||||
$where = [];
|
||||
$orWhere = [];
|
||||
|
||||
if (!empty($keyword)) {
|
||||
$where[] = ['work_name', 'like', '%' . $keyword . '%'];
|
||||
$orWhere[] = ['reg_number', 'like', '%' . $keyword . '%'];
|
||||
}
|
||||
|
||||
return FictionLibraryModel::where($where)->orWhere($orWhere)->offset($page)->limit($limit)->get($fields)->toArray();
|
||||
}
|
||||
}
|
44
app/copyright/controller/FictionController.php
Normal file
44
app/copyright/controller/FictionController.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace app\copyright\controller;
|
||||
|
||||
use app\copyright\exception\ApiException;
|
||||
use app\copyright\exception\EnumCode;
|
||||
use support\Request;
|
||||
use DI\Annotation\Inject;
|
||||
use app\copyright\validator\FictionValidator;
|
||||
use app\copyright\service\FictionService;
|
||||
|
||||
class FictionController
|
||||
{
|
||||
/**
|
||||
* @Inject
|
||||
*
|
||||
* @var FictionValidator
|
||||
*/
|
||||
private $fictionValidator;
|
||||
|
||||
/**
|
||||
* @Inject
|
||||
*
|
||||
* @var FictionService
|
||||
*/
|
||||
private $fictionService;
|
||||
|
||||
public function list(Request $request)
|
||||
{
|
||||
$params = [
|
||||
'page' => $request->get('page', 1),
|
||||
'limit' => $request->get('limit', 20),
|
||||
'keyword' => $request->get('keyword' , '')
|
||||
];
|
||||
|
||||
if (!$this->fictionValidator->check($params)) {
|
||||
throw new ApiException((string)$this->fictionValidator->getError(), EnumCode::ValidatorError);
|
||||
}
|
||||
|
||||
$data = $this->fictionService->list($params);
|
||||
|
||||
return json(['code' => 200, 'msg' => 'ok', 'data' => $data]);
|
||||
}
|
||||
}
|
7
app/copyright/exception/ApiException.php
Normal file
7
app/copyright/exception/ApiException.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace app\copyright\exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
class ApiException extends Exception{}
|
10
app/copyright/exception/EnumCode.php
Normal file
10
app/copyright/exception/EnumCode.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace app\copyright\exception;
|
||||
|
||||
class EnumCode
|
||||
{
|
||||
const Success = 200;
|
||||
const Error = 500;
|
||||
const ValidatorError = 400;
|
||||
}
|
28
app/copyright/service/FictionService.php
Normal file
28
app/copyright/service/FictionService.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace app\copyright\service;
|
||||
|
||||
use DI\Annotation\Inject;
|
||||
use app\common\repository\FictionLibraryRepository;
|
||||
|
||||
class FictionService
|
||||
{
|
||||
|
||||
/**
|
||||
* @Inject
|
||||
*
|
||||
* @var FictionLibraryRepository
|
||||
*/
|
||||
private $fictionLibraryRepository;
|
||||
|
||||
public function list(array $params)
|
||||
{
|
||||
$limit = $params['limit'];
|
||||
$page = ($params['page'] - 1) * $limit;
|
||||
$keyword = $params['keyword'];
|
||||
|
||||
$data = $this->fictionLibraryRepository->selectAll(['work_name', 'reg_number'], $page, $limit, $keyword);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
15
app/copyright/validator/FictionValidator.php
Normal file
15
app/copyright/validator/FictionValidator.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace app\copyright\validator;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class FictionValidator extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'page' => 'require',
|
||||
'limit' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [];
|
||||
}
|
4
app/functions.php
Normal file
4
app/functions.php
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Here is your custom functions.
|
||||
*/
|
65
composer.json
Normal file
65
composer.json
Normal file
@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "workerman/webman",
|
||||
"type": "project",
|
||||
"keywords": [
|
||||
"high performance",
|
||||
"http service"
|
||||
],
|
||||
"homepage": "https://www.workerman.net",
|
||||
"license": "MIT",
|
||||
"description": "High performance HTTP Service Framework.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "walkor",
|
||||
"email": "walkor@workerman.net",
|
||||
"homepage": "https://www.workerman.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"email": "walkor@workerman.net",
|
||||
"issues": "https://github.com/walkor/webman/issues",
|
||||
"forum": "https://wenda.workerman.net/",
|
||||
"wiki": "https://workerman.net/doc/webman",
|
||||
"source": "https://github.com/walkor/webman"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"workerman/webman-framework": "^1.4.3",
|
||||
"monolog/monolog": "^2.0",
|
||||
"topthink/think-validate": "^2.0",
|
||||
"psr/container": "^1.1.1",
|
||||
"illuminate/database": "^9.50",
|
||||
"illuminate/pagination": "^9.50",
|
||||
"illuminate/events": "^9.50",
|
||||
"symfony/var-dumper": "^6.2",
|
||||
"php-di/php-di": "^6",
|
||||
"doctrine/annotations": "^1.14",
|
||||
"webman-tech/docker": "^2.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"": "./",
|
||||
"app\\": "./app",
|
||||
"App\\": "./app",
|
||||
"app\\View\\Components\\": "./app/view/components"
|
||||
},
|
||||
"files": [
|
||||
"./support/helpers.php"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"post-package-install": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"post-package-update": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"pre-package-uninstall": [
|
||||
"support\\Plugin::uninstall"
|
||||
]
|
||||
}
|
||||
}
|
3292
composer.lock
generated
Normal file
3292
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
config/app.php
Normal file
26
config/app.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\Request;
|
||||
|
||||
return [
|
||||
'debug' => true,
|
||||
'error_reporting' => E_ALL,
|
||||
'default_timezone' => 'Asia/Shanghai',
|
||||
'request_class' => Request::class,
|
||||
'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public',
|
||||
'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime',
|
||||
'controller_suffix' => 'Controller',
|
||||
'controller_reuse' => false,
|
||||
];
|
21
config/autoload.php
Normal file
21
config/autoload.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'files' => [
|
||||
base_path() . '/app/functions.php',
|
||||
base_path() . '/support/Request.php',
|
||||
base_path() . '/support/Response.php',
|
||||
]
|
||||
];
|
18
config/bootstrap.php
Normal file
18
config/bootstrap.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
support\bootstrap\Session::class,
|
||||
support\bootstrap\LaravelDb::class,
|
||||
];
|
20
config/container.php
Normal file
20
config/container.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
$builder = new \DI\ContainerBuilder();
|
||||
$builder->addDefinitions(config('dependence', []));
|
||||
$builder->useAutowiring(true);
|
||||
$builder->useAnnotations(true);
|
||||
return $builder->build();
|
34
config/database.php
Normal file
34
config/database.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => 'mysql',
|
||||
'connections' => [
|
||||
'mysql' => [
|
||||
'driver' => 'mysql',
|
||||
'host' => '',
|
||||
'port' => 3306,
|
||||
'database' => 'copyright',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'unix_socket' => '',
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
'prefix' => '',
|
||||
'strict' => true,
|
||||
'engine' => null,
|
||||
],
|
||||
],
|
||||
];
|
15
config/dependence.php
Normal file
15
config/dependence.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
18
config/exception.php
Normal file
18
config/exception.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'' => support\exception\Handler::class,
|
||||
'api' => support\ApiHandler::class
|
||||
];
|
32
config/log.php
Normal file
32
config/log.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'handlers' => [
|
||||
[
|
||||
'class' => Monolog\Handler\RotatingFileHandler::class,
|
||||
'constructor' => [
|
||||
runtime_path() . '/logs/webman.log',
|
||||
7, //$maxFiles
|
||||
Monolog\Logger::DEBUG,
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [null, 'Y-m-d H:i:s', true],
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
15
config/middleware.php
Normal file
15
config/middleware.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
42
config/process.php
Normal file
42
config/process.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Workerman\Worker;
|
||||
|
||||
return [
|
||||
// File update detection and automatic reload
|
||||
'monitor' => [
|
||||
'handler' => process\Monitor::class,
|
||||
'reloadable' => false,
|
||||
'constructor' => [
|
||||
// Monitor these directories
|
||||
'monitor_dir' => array_merge([
|
||||
app_path(),
|
||||
config_path(),
|
||||
base_path() . '/process',
|
||||
base_path() . '/support',
|
||||
base_path() . '/resource',
|
||||
base_path() . '/.env',
|
||||
], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')),
|
||||
// Files with these suffixes will be monitored
|
||||
'monitor_extensions' => [
|
||||
'php', 'html', 'htm', 'env'
|
||||
],
|
||||
'options' => [
|
||||
'enable_file_monitor' => !Worker::$daemonize && DIRECTORY_SEPARATOR === '/',
|
||||
'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/',
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
22
config/redis.php
Normal file
22
config/redis.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'host' => '127.0.0.1',
|
||||
'password' => null,
|
||||
'port' => 6379,
|
||||
'database' => 0,
|
||||
],
|
||||
];
|
20
config/route.php
Normal file
20
config/route.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Webman\Route;
|
||||
|
||||
Route::group('/api' , function(){
|
||||
Route::get('/fiction-list', [\app\copyright\controller\FictionController::class, 'list']);
|
||||
});
|
31
config/server.php
Normal file
31
config/server.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'listen' => 'http://0.0.0.0:8787',
|
||||
'transport' => 'tcp',
|
||||
'context' => [],
|
||||
'name' => 'webman',
|
||||
'count' => cpu_count() * 4,
|
||||
'user' => '',
|
||||
'group' => '',
|
||||
'reusePort' => false,
|
||||
'event_loop' => '',
|
||||
'stop_timeout' => 2,
|
||||
'pid_file' => runtime_path() . '/webman.pid',
|
||||
'status_file' => runtime_path() . '/webman.status',
|
||||
'stdout_file' => runtime_path() . '/logs/stdout.log',
|
||||
'log_file' => runtime_path() . '/logs/workerman.log',
|
||||
'max_package_size' => 10 * 1024 * 1024
|
||||
];
|
65
config/session.php
Normal file
65
config/session.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Webman\Session\FileSessionHandler;
|
||||
use Webman\Session\RedisSessionHandler;
|
||||
use Webman\Session\RedisClusterSessionHandler;
|
||||
|
||||
return [
|
||||
|
||||
'type' => 'file', // or redis or redis_cluster
|
||||
|
||||
'handler' => FileSessionHandler::class,
|
||||
|
||||
'config' => [
|
||||
'file' => [
|
||||
'save_path' => runtime_path() . '/sessions',
|
||||
],
|
||||
'redis' => [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'auth' => '',
|
||||
'timeout' => 2,
|
||||
'database' => '',
|
||||
'prefix' => 'redis_session_',
|
||||
],
|
||||
'redis_cluster' => [
|
||||
'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'],
|
||||
'timeout' => 2,
|
||||
'auth' => '',
|
||||
'prefix' => 'redis_session_',
|
||||
]
|
||||
],
|
||||
|
||||
'session_name' => 'PHPSID',
|
||||
|
||||
'auto_update_timestamp' => false,
|
||||
|
||||
'lifetime' => 7*24*60*60,
|
||||
|
||||
'cookie_lifetime' => 365*24*60*60,
|
||||
|
||||
'cookie_path' => '/',
|
||||
|
||||
'domain' => '',
|
||||
|
||||
'http_only' => true,
|
||||
|
||||
'secure' => false,
|
||||
|
||||
'same_site' => '',
|
||||
|
||||
'gc_probability' => [1, 1000],
|
||||
|
||||
];
|
23
config/static.php
Normal file
23
config/static.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Static file settings
|
||||
*/
|
||||
return [
|
||||
'enable' => true,
|
||||
'middleware' => [ // Static file Middleware
|
||||
//app\middleware\StaticFile::class,
|
||||
],
|
||||
];
|
25
config/translation.php
Normal file
25
config/translation.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Multilingual configuration
|
||||
*/
|
||||
return [
|
||||
// Default language
|
||||
'locale' => 'zh_CN',
|
||||
// Fallback language
|
||||
'fallback_locale' => ['zh_CN', 'en'],
|
||||
// Folder where language files are stored
|
||||
'path' => base_path() . '/resource/translations',
|
||||
];
|
22
config/view.php
Normal file
22
config/view.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\view\Raw;
|
||||
use support\view\Twig;
|
||||
use support\view\Blade;
|
||||
use support\view\ThinkPHP;
|
||||
|
||||
return [
|
||||
'handler' => Raw::class
|
||||
];
|
9
docker-compose.yml
Normal file
9
docker-compose.yml
Normal file
@ -0,0 +1,9 @@
|
||||
version: "3.7"
|
||||
|
||||
services:
|
||||
webman:
|
||||
image: krisss/docker-webman:${DOCKER_WEBMAN_VERSION:-8.1-cli-alpine}
|
||||
ports:
|
||||
- "${DOCKER_WEBMAN_PORT:-8787}:8787"
|
||||
volumes:
|
||||
- .:/app
|
240
process/Monitor.php
Normal file
240
process/Monitor.php
Normal file
@ -0,0 +1,240 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace process;
|
||||
|
||||
use Workerman\Timer;
|
||||
use Workerman\Worker;
|
||||
|
||||
/**
|
||||
* Class FileMonitor
|
||||
* @package process
|
||||
*/
|
||||
class Monitor
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $_paths = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $_extensions = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public static $lockFile = __DIR__ . '/../runtime/monitor.lock';
|
||||
|
||||
/**
|
||||
* Pause monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function pause()
|
||||
{
|
||||
file_put_contents(static::$lockFile, time());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function resume()
|
||||
{
|
||||
clearstatcache();
|
||||
if (is_file(static::$lockFile)) {
|
||||
unlink(static::$lockFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether monitor is paused
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPaused(): bool
|
||||
{
|
||||
clearstatcache();
|
||||
return file_exists(static::$lockFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* FileMonitor constructor.
|
||||
* @param $monitor_dir
|
||||
* @param $monitor_extensions
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct($monitor_dir, $monitor_extensions, array $options = [])
|
||||
{
|
||||
static::resume();
|
||||
$this->_paths = (array)$monitor_dir;
|
||||
$this->_extensions = $monitor_extensions;
|
||||
if (!Worker::getAllWorkers()) {
|
||||
return;
|
||||
}
|
||||
$disable_functions = explode(',', ini_get('disable_functions'));
|
||||
if (in_array('exec', $disable_functions, true)) {
|
||||
echo "\nMonitor file change turned off because exec() has been disabled by disable_functions setting in " . PHP_CONFIG_FILE_PATH . "/php.ini\n";
|
||||
} else {
|
||||
if ($options['enable_file_monitor'] ?? true) {
|
||||
Timer::add(1, function () {
|
||||
$this->checkAllFilesChange();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$memory_limit = $this->getMemoryLimit($options['memory_limit'] ?? null);
|
||||
if ($options['enable_memory_monitor'] ?? $memory_limit) {
|
||||
Timer::add(60, [$this, 'checkMemory'], [$memory_limit]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $monitor_dir
|
||||
* @return bool
|
||||
*/
|
||||
public function checkFilesChange($monitor_dir): bool
|
||||
{
|
||||
static $last_mtime, $too_many_files_check;
|
||||
if (!$last_mtime) {
|
||||
$last_mtime = time();
|
||||
}
|
||||
clearstatcache();
|
||||
if (!is_dir($monitor_dir)) {
|
||||
if (!is_file($monitor_dir)) {
|
||||
return false;
|
||||
}
|
||||
$iterator = [new \SplFileInfo($monitor_dir)];
|
||||
} else {
|
||||
// recursive traversal directory
|
||||
$dir_iterator = new \RecursiveDirectoryIterator($monitor_dir, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS);
|
||||
$iterator = new \RecursiveIteratorIterator($dir_iterator);
|
||||
}
|
||||
$count = 0;
|
||||
foreach ($iterator as $file) {
|
||||
$count ++;
|
||||
/** var SplFileInfo $file */
|
||||
if (is_dir($file->getRealPath())) {
|
||||
continue;
|
||||
}
|
||||
// check mtime
|
||||
if ($last_mtime < $file->getMTime() && in_array($file->getExtension(), $this->_extensions, true)) {
|
||||
$var = 0;
|
||||
exec('"'.PHP_BINARY . '" -l ' . $file, $out, $var);
|
||||
if ($var) {
|
||||
$last_mtime = $file->getMTime();
|
||||
continue;
|
||||
}
|
||||
$last_mtime = $file->getMTime();
|
||||
echo $file . " update and reload\n";
|
||||
// send SIGUSR1 signal to master process for reload
|
||||
if (DIRECTORY_SEPARATOR === '/') {
|
||||
posix_kill(posix_getppid(), SIGUSR1);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$too_many_files_check && $count > 1000) {
|
||||
echo "Monitor: There are too many files ($count files) in $monitor_dir which makes file monitoring very slow\n";
|
||||
$too_many_files_check = 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function checkAllFilesChange(): bool
|
||||
{
|
||||
if (static::isPaused()) {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->_paths as $path) {
|
||||
if ($this->checkFilesChange($path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $memory_limit
|
||||
* @return void
|
||||
*/
|
||||
public function checkMemory($memory_limit)
|
||||
{
|
||||
if (static::isPaused()) {
|
||||
return;
|
||||
}
|
||||
$ppid = posix_getppid();
|
||||
$children_file = "/proc/$ppid/task/$ppid/children";
|
||||
if (!is_file($children_file) || !($children = file_get_contents($children_file))) {
|
||||
return;
|
||||
}
|
||||
foreach (explode(' ', $children) as $pid) {
|
||||
$pid = (int)$pid;
|
||||
$status_file = "/proc/$pid/status";
|
||||
if (!is_file($status_file) || !($status = file_get_contents($status_file))) {
|
||||
continue;
|
||||
}
|
||||
$mem = 0;
|
||||
if (preg_match('/VmRSS\s*?:\s*?(\d+?)\s*?kB/', $status, $match)) {
|
||||
$mem = $match[1];
|
||||
}
|
||||
$mem = (int)($mem / 1024);
|
||||
if ($mem >= $memory_limit) {
|
||||
posix_kill($pid, SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory limit
|
||||
* @return float
|
||||
*/
|
||||
protected function getMemoryLimit($memory_limit)
|
||||
{
|
||||
if ($memory_limit === 0) {
|
||||
return 0;
|
||||
}
|
||||
$use_php_ini = false;
|
||||
if (!$memory_limit) {
|
||||
$memory_limit = ini_get('memory_limit');
|
||||
$use_php_ini = true;
|
||||
}
|
||||
|
||||
if ($memory_limit == -1) {
|
||||
return 0;
|
||||
}
|
||||
$unit = $memory_limit[strlen($memory_limit) - 1];
|
||||
if ($unit == 'G') {
|
||||
$memory_limit = 1024 * (int)$memory_limit;
|
||||
} else if ($unit == 'M') {
|
||||
$memory_limit = (int)$memory_limit;
|
||||
} else if ($unit == 'K') {
|
||||
$memory_limit = (int)($memory_limit / 1024);
|
||||
} else {
|
||||
$memory_limit = (int)($memory_limit / (1024 * 1024));
|
||||
}
|
||||
if ($memory_limit < 30) {
|
||||
$memory_limit = 30;
|
||||
}
|
||||
if ($use_php_ini) {
|
||||
$memory_limit = (int)(0.8 * $memory_limit);
|
||||
}
|
||||
return $memory_limit;
|
||||
}
|
||||
}
|
12
public/404.html
Normal file
12
public/404.html
Normal file
@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>404 Not Found - webman</title>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<h1>404 Not Found</h1>
|
||||
</center>
|
||||
<hr>
|
||||
<center><a href="https://www.workerman.net">webman</a></center>
|
||||
</body>
|
||||
</html>
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
4
runtime/.gitignore
vendored
Normal file
4
runtime/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*
|
||||
!logs
|
||||
!views
|
||||
!.gitignore
|
2
runtime/logs/.gitignore
vendored
Normal file
2
runtime/logs/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
2
runtime/views/.gitignore
vendored
Normal file
2
runtime/views/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
4
start.php
Normal file
4
start.php
Normal file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
support\App::run();
|
25
support/ApiHandler.php
Normal file
25
support/ApiHandler.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace support;
|
||||
|
||||
use app\copyright\exception\ApiException;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Throwable;
|
||||
use Webman\Exception\ExceptionHandlerInterface;
|
||||
|
||||
class ApiHandler implements ExceptionHandlerInterface
|
||||
{
|
||||
public function report(Throwable $e)
|
||||
{
|
||||
}
|
||||
|
||||
public function render(Request $request, Throwable $e): Response
|
||||
{
|
||||
if ($e instanceof ApiException){
|
||||
return json(['code' => $e->getCode() , 'msg' => $e->getMessage()]);
|
||||
}
|
||||
|
||||
return json([]);
|
||||
}
|
||||
}
|
24
support/Request.php
Normal file
24
support/Request.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace support;
|
||||
|
||||
/**
|
||||
* Class Request
|
||||
* @package support
|
||||
*/
|
||||
class Request extends \Webman\Http\Request
|
||||
{
|
||||
|
||||
}
|
24
support/Response.php
Normal file
24
support/Response.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace support;
|
||||
|
||||
/**
|
||||
* Class Response
|
||||
* @package support
|
||||
*/
|
||||
class Response extends \Webman\Http\Response
|
||||
{
|
||||
|
||||
}
|
132
support/bootstrap.php
Normal file
132
support/bootstrap.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use support\Log;
|
||||
use Webman\Bootstrap;
|
||||
use Webman\Config;
|
||||
use Webman\Route;
|
||||
use Webman\Middleware;
|
||||
use Webman\Util;
|
||||
|
||||
$worker = $worker ?? null;
|
||||
|
||||
set_error_handler(function ($level, $message, $file = '', $line = 0) {
|
||||
if (error_reporting() & $level) {
|
||||
throw new ErrorException($message, 0, $level, $file, $line);
|
||||
}
|
||||
});
|
||||
|
||||
if ($worker) {
|
||||
register_shutdown_function(function ($start_time) {
|
||||
if (time() - $start_time <= 1) {
|
||||
sleep(1);
|
||||
}
|
||||
}, time());
|
||||
}
|
||||
|
||||
if (class_exists('Dotenv\Dotenv') && file_exists(base_path() . '/.env')) {
|
||||
if (method_exists('Dotenv\Dotenv', 'createUnsafeImmutable')) {
|
||||
Dotenv::createUnsafeImmutable(base_path())->load();
|
||||
} else {
|
||||
Dotenv::createMutable(base_path())->load();
|
||||
}
|
||||
}
|
||||
|
||||
Config::clear();
|
||||
support\App::loadAllConfig(['route']);
|
||||
if ($timezone = config('app.default_timezone')) {
|
||||
date_default_timezone_set($timezone);
|
||||
}
|
||||
|
||||
foreach (config('autoload.files', []) as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['autoload']['files'] ?? [] as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
}
|
||||
foreach ($projects['autoload']['files'] ?? [] as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
}
|
||||
|
||||
Middleware::load(config('middleware', []), '');
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project) || $name === 'static') {
|
||||
continue;
|
||||
}
|
||||
Middleware::load($project['middleware'] ?? [], '');
|
||||
}
|
||||
Middleware::load($projects['middleware'] ?? [], $firm);
|
||||
if ($static_middlewares = config("plugin.$firm.static.middleware")) {
|
||||
Middleware::load(['__static__' => $static_middlewares], $firm);
|
||||
}
|
||||
}
|
||||
Middleware::load(['__static__' => config('static.middleware', [])], '');
|
||||
|
||||
foreach (config('bootstrap', []) as $class_name) {
|
||||
if (!class_exists($class_name)) {
|
||||
$log = "Warning: Class $class_name setting in config/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $class_name */
|
||||
$class_name::start($worker);
|
||||
}
|
||||
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['bootstrap'] ?? [] as $class_name) {
|
||||
if (!class_exists($class_name)) {
|
||||
$log = "Warning: Class $class_name setting in config/plugin/$firm/$name/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $class_name */
|
||||
$class_name::start($worker);
|
||||
}
|
||||
}
|
||||
foreach ($projects['bootstrap'] ?? [] as $class_name) {
|
||||
if (!class_exists($class_name)) {
|
||||
$log = "Warning: Class $class_name setting in plugin/$firm/config/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $class_name */
|
||||
$class_name::start($worker);
|
||||
}
|
||||
}
|
||||
|
||||
$directory = base_path() . '/plugin';
|
||||
$paths = [config_path()];
|
||||
foreach (Util::scanDir($directory) as $path) {
|
||||
if (is_dir($path = "$path/config")) {
|
||||
$paths[] = $path;
|
||||
}
|
||||
}
|
||||
Route::load($paths);
|
||||
|
525
support/helpers.php
Normal file
525
support/helpers.php
Normal file
@ -0,0 +1,525 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\Container;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use support\Translation;
|
||||
use support\view\Raw;
|
||||
use support\view\Blade;
|
||||
use support\view\ThinkPHP;
|
||||
use support\view\Twig;
|
||||
use Workerman\Worker;
|
||||
use Webman\App;
|
||||
use Webman\Config;
|
||||
use Webman\Route;
|
||||
|
||||
// Webman version
|
||||
const WEBMAN_VERSION = '1.4';
|
||||
|
||||
// Project base path
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
|
||||
/**
|
||||
* return the program execute directory
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function run_path(string $path = ''): string
|
||||
{
|
||||
static $run_path = '';
|
||||
if (!$run_path) {
|
||||
$run_path = \is_phar() ? \dirname(\Phar::running(false)) : BASE_PATH;
|
||||
}
|
||||
return \path_combine($run_path, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* if the param $path equal false,will return this program current execute directory
|
||||
* @param string|false $path
|
||||
* @return string
|
||||
*/
|
||||
function base_path($path = ''): string
|
||||
{
|
||||
if (false === $path) {
|
||||
return \run_path();
|
||||
}
|
||||
return \path_combine(BASE_PATH, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* App path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function app_path(string $path = ''): string
|
||||
{
|
||||
return \path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function public_path(string $path = ''): string
|
||||
{
|
||||
static $public_path = '';
|
||||
if (!$public_path) {
|
||||
$public_path = \config('app.public_path') ? : \run_path('public');
|
||||
}
|
||||
return \path_combine($public_path, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Config path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function config_path(string $path = ''): string
|
||||
{
|
||||
return \path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runtime path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function runtime_path(string $path = ''): string
|
||||
{
|
||||
static $runtime_path = '';
|
||||
if (!$runtime_path) {
|
||||
$runtime_path = \config('app.runtime_path') ? : \run_path('runtime');
|
||||
}
|
||||
return \path_combine($runtime_path, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate paths based on given information
|
||||
* @param string $front
|
||||
* @param string $back
|
||||
* @return string
|
||||
*/
|
||||
function path_combine(string $front, string $back): string
|
||||
{
|
||||
return $front . ($back ? (DIRECTORY_SEPARATOR . ltrim($back, DIRECTORY_SEPARATOR)) : $back);
|
||||
}
|
||||
|
||||
/**
|
||||
* Response
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param string $body
|
||||
* @return Response
|
||||
*/
|
||||
function response(string $body = '', int $status = 200, array $headers = []): Response
|
||||
{
|
||||
return new Response($status, $headers, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Json response
|
||||
* @param $data
|
||||
* @param int $options
|
||||
* @return Response
|
||||
*/
|
||||
function json($data, int $options = JSON_UNESCAPED_UNICODE): Response
|
||||
{
|
||||
return new Response(200, ['Content-Type' => 'application/json'], \json_encode($data, $options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Xml response
|
||||
* @param $xml
|
||||
* @return Response
|
||||
*/
|
||||
function xml($xml): Response
|
||||
{
|
||||
if ($xml instanceof SimpleXMLElement) {
|
||||
$xml = $xml->asXML();
|
||||
}
|
||||
return new Response(200, ['Content-Type' => 'text/xml'], $xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Jsonp response
|
||||
* @param $data
|
||||
* @param string $callback_name
|
||||
* @return Response
|
||||
*/
|
||||
function jsonp($data, string $callback_name = 'callback'): Response
|
||||
{
|
||||
if (!\is_scalar($data) && null !== $data) {
|
||||
$data = \json_encode($data);
|
||||
}
|
||||
return new Response(200, [], "$callback_name($data)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect response
|
||||
* @param string $location
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return Response
|
||||
*/
|
||||
function redirect(string $location, int $status = 302, array $headers = []): Response
|
||||
{
|
||||
$response = new Response($status, ['Location' => $location]);
|
||||
if (!empty($headers)) {
|
||||
$response->withHeaders($headers);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* View response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
*/
|
||||
function view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
$request = \request();
|
||||
$plugin = $request->plugin ?? '';
|
||||
$handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
|
||||
return new Response(200, [], $handler::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
* @throws Throwable
|
||||
*/
|
||||
function raw_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Raw::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Blade view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
*/
|
||||
function blade_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Blade::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Think view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
*/
|
||||
function think_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], ThinkPHP::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Twig view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
*/
|
||||
function twig_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Twig::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request
|
||||
* @return \Webman\Http\Request|Request|null
|
||||
*/
|
||||
function request()
|
||||
{
|
||||
return App::request();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config
|
||||
* @param string|null $key
|
||||
* @param $default
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
function config(string $key = null, $default = null)
|
||||
{
|
||||
return Config::get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create url
|
||||
* @param string $name
|
||||
* @param ...$parameters
|
||||
* @return string
|
||||
*/
|
||||
function route(string $name, ...$parameters): string
|
||||
{
|
||||
$route = Route::getByName($name);
|
||||
if (!$route) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$parameters) {
|
||||
return $route->url();
|
||||
}
|
||||
|
||||
if (\is_array(\current($parameters))) {
|
||||
$parameters = \current($parameters);
|
||||
}
|
||||
|
||||
return $route->url($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Session
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
function session($key = null, $default = null)
|
||||
{
|
||||
$session = \request()->session();
|
||||
if (null === $key) {
|
||||
return $session;
|
||||
}
|
||||
if (\is_array($key)) {
|
||||
$session->put($key);
|
||||
return null;
|
||||
}
|
||||
if (\strpos($key, '.')) {
|
||||
$key_array = \explode('.', $key);
|
||||
$value = $session->all();
|
||||
foreach ($key_array as $index) {
|
||||
if (!isset($value[$index])) {
|
||||
return $default;
|
||||
}
|
||||
$value = $value[$index];
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
return $session->get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translation
|
||||
* @param string $id
|
||||
* @param array $parameters
|
||||
* @param string|null $domain
|
||||
* @param string|null $locale
|
||||
* @return string
|
||||
*/
|
||||
function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string
|
||||
{
|
||||
$res = Translation::trans($id, $parameters, $domain, $locale);
|
||||
return $res === '' ? $id : $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locale
|
||||
* @param string|null $locale
|
||||
* @return void
|
||||
*/
|
||||
function locale(string $locale = null): string
|
||||
{
|
||||
if (!$locale) {
|
||||
return Translation::getLocale();
|
||||
}
|
||||
Translation::setLocale($locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* 404 not found
|
||||
* @return Response
|
||||
*/
|
||||
function not_found(): Response
|
||||
{
|
||||
return new Response(404, [], \file_get_contents(public_path() . '/404.html'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy dir
|
||||
* @param string $source
|
||||
* @param string $dest
|
||||
* @param bool $overwrite
|
||||
* @return void
|
||||
*/
|
||||
function copy_dir(string $source, string $dest, bool $overwrite = false)
|
||||
{
|
||||
if (\is_dir($source)) {
|
||||
if (!is_dir($dest)) {
|
||||
\mkdir($dest);
|
||||
}
|
||||
$files = \scandir($source);
|
||||
foreach ($files as $file) {
|
||||
if ($file !== "." && $file !== "..") {
|
||||
\copy_dir("$source/$file", "$dest/$file");
|
||||
}
|
||||
}
|
||||
} else if (\file_exists($source) && ($overwrite || !\file_exists($dest))) {
|
||||
\copy($source, $dest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove dir
|
||||
* @param string $dir
|
||||
* @return bool
|
||||
*/
|
||||
function remove_dir(string $dir): bool
|
||||
{
|
||||
if (\is_link($dir) || \is_file($dir)) {
|
||||
return \unlink($dir);
|
||||
}
|
||||
$files = \array_diff(\scandir($dir), array('.', '..'));
|
||||
foreach ($files as $file) {
|
||||
(\is_dir("$dir/$file") && !\is_link($dir)) ? \remove_dir("$dir/$file") : \unlink("$dir/$file");
|
||||
}
|
||||
return \rmdir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind worker
|
||||
* @param $worker
|
||||
* @param $class
|
||||
*/
|
||||
function worker_bind($worker, $class)
|
||||
{
|
||||
$callback_map = [
|
||||
'onConnect',
|
||||
'onMessage',
|
||||
'onClose',
|
||||
'onError',
|
||||
'onBufferFull',
|
||||
'onBufferDrain',
|
||||
'onWorkerStop',
|
||||
'onWebSocketConnect'
|
||||
];
|
||||
foreach ($callback_map as $name) {
|
||||
if (\method_exists($class, $name)) {
|
||||
$worker->$name = [$class, $name];
|
||||
}
|
||||
}
|
||||
if (\method_exists($class, 'onWorkerStart')) {
|
||||
\call_user_func([$class, 'onWorkerStart'], $worker);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start worker
|
||||
* @param $process_name
|
||||
* @param $config
|
||||
* @return void
|
||||
*/
|
||||
function worker_start($process_name, $config)
|
||||
{
|
||||
$worker = new Worker($config['listen'] ?? null, $config['context'] ?? []);
|
||||
$property_map = [
|
||||
'count',
|
||||
'user',
|
||||
'group',
|
||||
'reloadable',
|
||||
'reusePort',
|
||||
'transport',
|
||||
'protocol',
|
||||
];
|
||||
$worker->name = $process_name;
|
||||
foreach ($property_map as $property) {
|
||||
if (isset($config[$property])) {
|
||||
$worker->$property = $config[$property];
|
||||
}
|
||||
}
|
||||
|
||||
$worker->onWorkerStart = function ($worker) use ($config) {
|
||||
require_once \base_path() . '/support/bootstrap.php';
|
||||
|
||||
foreach ($config['services'] ?? [] as $server) {
|
||||
if (!\class_exists($server['handler'])) {
|
||||
echo "process error: class {$server['handler']} not exists\r\n";
|
||||
continue;
|
||||
}
|
||||
$listen = new Worker($server['listen'] ?? null, $server['context'] ?? []);
|
||||
if (isset($server['listen'])) {
|
||||
echo "listen: {$server['listen']}\n";
|
||||
}
|
||||
$instance = Container::make($server['handler'], $server['constructor'] ?? []);
|
||||
\worker_bind($listen, $instance);
|
||||
$listen->listen();
|
||||
}
|
||||
|
||||
if (isset($config['handler'])) {
|
||||
if (!\class_exists($config['handler'])) {
|
||||
echo "process error: class {$config['handler']} not exists\r\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = Container::make($config['handler'], $config['constructor'] ?? []);
|
||||
\worker_bind($worker, $instance);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get realpath
|
||||
* @param string $file_path
|
||||
* @return string
|
||||
*/
|
||||
function get_realpath(string $file_path): string
|
||||
{
|
||||
if (\strpos($file_path, 'phar://') === 0) {
|
||||
return $file_path;
|
||||
} else {
|
||||
return \realpath($file_path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is phar
|
||||
* @return bool
|
||||
*/
|
||||
function is_phar(): bool
|
||||
{
|
||||
return \class_exists(\Phar::class, false) && Phar::running();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cpu count
|
||||
* @return int
|
||||
*/
|
||||
function cpu_count(): int
|
||||
{
|
||||
// Windows does not support the number of processes setting.
|
||||
if (\DIRECTORY_SEPARATOR === '\\') {
|
||||
return 1;
|
||||
}
|
||||
$count = 4;
|
||||
if (\is_callable('shell_exec')) {
|
||||
if (\strtolower(PHP_OS) === 'darwin') {
|
||||
$count = (int)\shell_exec('sysctl -n machdep.cpu.core_count');
|
||||
} else {
|
||||
$count = (int)\shell_exec('nproc');
|
||||
}
|
||||
}
|
||||
return $count > 0 ? $count : 4;
|
||||
}
|
3
windows.bat
Normal file
3
windows.bat
Normal file
@ -0,0 +1,3 @@
|
||||
CHCP 65001
|
||||
php windows.php
|
||||
pause
|
116
windows.php
Normal file
116
windows.php
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
/**
|
||||
* Start file for windows
|
||||
*/
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use process\Monitor;
|
||||
use support\App;
|
||||
use Dotenv\Dotenv;
|
||||
use Workerman\Worker;
|
||||
|
||||
ini_set('display_errors', 'on');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (class_exists('Dotenv\Dotenv') && file_exists(base_path() . '/.env')) {
|
||||
if (method_exists('Dotenv\Dotenv', 'createUnsafeImmutable')) {
|
||||
Dotenv::createUnsafeImmutable(base_path())->load();
|
||||
} else {
|
||||
Dotenv::createMutable(base_path())->load();
|
||||
}
|
||||
}
|
||||
|
||||
App::loadAllConfig(['route']);
|
||||
|
||||
$error_reporting = config('app.error_reporting');
|
||||
if (isset($error_reporting)) {
|
||||
error_reporting($error_reporting);
|
||||
}
|
||||
|
||||
$runtime_process_path = runtime_path() . DIRECTORY_SEPARATOR . '/windows';
|
||||
if (!is_dir($runtime_process_path)) {
|
||||
mkdir($runtime_process_path);
|
||||
}
|
||||
$process_files = [
|
||||
__DIR__ . DIRECTORY_SEPARATOR . 'start.php'
|
||||
];
|
||||
foreach (config('process', []) as $process_name => $config) {
|
||||
$process_files[] = write_process_file($runtime_process_path, $process_name, '');
|
||||
}
|
||||
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['process'] ?? [] as $process_name => $config) {
|
||||
$process_files[] = write_process_file($runtime_process_path, $process_name, "$firm.$name");
|
||||
}
|
||||
}
|
||||
foreach ($projects['process'] ?? [] as $process_name => $config) {
|
||||
$process_files[] = write_process_file($runtime_process_path, $process_name, $firm);
|
||||
}
|
||||
}
|
||||
|
||||
function write_process_file($runtime_process_path, $process_name, $firm)
|
||||
{
|
||||
$process_param = $firm ? "plugin.$firm.$process_name" : $process_name;
|
||||
$config_param = $firm ? "config('plugin.$firm.process')['$process_name']" : "config('process')['$process_name']";
|
||||
$file_content = <<<EOF
|
||||
<?php
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use Workerman\Worker;
|
||||
use Webman\Config;
|
||||
use support\App;
|
||||
|
||||
ini_set('display_errors', 'on');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (is_callable('opcache_reset')) {
|
||||
opcache_reset();
|
||||
}
|
||||
|
||||
App::loadAllConfig(['route']);
|
||||
|
||||
worker_start('$process_param', $config_param);
|
||||
|
||||
if (DIRECTORY_SEPARATOR != "/") {
|
||||
Worker::\$logFile = config('server')['log_file'] ?? Worker::\$logFile;
|
||||
}
|
||||
|
||||
Worker::runAll();
|
||||
|
||||
EOF;
|
||||
$process_file = $runtime_process_path . DIRECTORY_SEPARATOR . "start_$process_param.php";
|
||||
file_put_contents($process_file, $file_content);
|
||||
return $process_file;
|
||||
}
|
||||
|
||||
if ($monitor_config = config('process.monitor.constructor')) {
|
||||
$monitor = new Monitor(...array_values($monitor_config));
|
||||
}
|
||||
|
||||
function popen_processes($process_files)
|
||||
{
|
||||
$cmd = "php " . implode(' ', $process_files);
|
||||
$descriptorspec = [STDIN, STDOUT, STDOUT];
|
||||
$resource = proc_open($cmd, $descriptorspec, $pipes);
|
||||
if (!$resource) {
|
||||
exit("Can not execute $cmd\r\n");
|
||||
}
|
||||
return $resource;
|
||||
}
|
||||
|
||||
$resource = popen_processes($process_files);
|
||||
echo "\r\n";
|
||||
while (1) {
|
||||
sleep(1);
|
||||
if (!empty($monitor) && $monitor->checkAllFilesChange()) {
|
||||
$status = proc_get_status($resource);
|
||||
$pid = $status['pid'];
|
||||
shell_exec("taskkill /F /T /PID $pid");
|
||||
proc_close($resource);
|
||||
$resource = popen_processes($process_files);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user