dcrswoole / framework
PHP coroutine framework.
Installs: 8
Dependents: 0
Suggesters: 0
Security: 0
Stars: 6
Watchers: 2
Forks: 1
Open Issues: 0
Type:project
Requires
- php: >=8.3.0
- ext-bcmath: *
- ext-curl: *
- ext-gd: *
- ext-json: *
- ext-libxml: *
- ext-openssl: *
- ext-pcntl: *
- ext-pdo: *
- ext-redis: *
- ext-simplexml: *
- ext-swoole: >=4.8
- casbin/casbin: ^3.20
- doctrine/annotations: ^2.0
- doctrine/migrations: ^3.5
- elasticsearch/elasticsearch: 7.16
- firebase/php-jwt: ^6.3
- gregwar/captcha: ^1.1
- guanhui07/database: dev-master
- guanhui07/dcr-swoole-crontab: dev-master
- guanhui07/guzzle: ^1.2
- guanhui07/redis: ^1.1
- hyperf/aop-integration: ^1.1
- hyperf/di: 3.0.0
- hyperf/utils: 3.0.0
- inhere/console: ^4.1
- inhere/php-validate: ^2.8
- intervention/image: ^2.7
- middlewares/utils: ^3.0
- monolog/monolog: ^2.8
- mwangithegreat/faker: ^1.9
- nesbot/carbon: ^2.6
- nikic/fast-route: ^1.3
- opis/closure: ^3.6
- php-amqplib/php-amqplib: ^3.2
- php-di/php-di: ^7.0
- qiniu/php-sdk: ^7.7
- spatie/image: ^2.2
- symfony/event-dispatcher: ^6.2
- symfony/finder: ^5.0
- vlucas/phpdotenv: ^5.4
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0.0
- phpstan/phpstan: ~1.8.0
- phpunit/php-timer: ^5.0
- phpunit/phpunit: ^9.5
- roave/security-advisories: dev-latest
- swoole/ide-helper: ^5.0
Suggests
- php: >=8.3
README
- laravel orm
- restful route
- predis
- guzzle
- monolog
- http websocket
- rabbitmq
- container
- event
- middleware 支持注解配置中间件
- validate
- crontab
- command
- collection
- carbon
- dotenv config
- 支持注解配置路由 注解配置中间件
- aop 切面
- process
安装
composer create-project dcrswoole/framework skeleton
cp .env.example .env
分层 (demo未按此方式)
controller->service ->repository->model
http:
php ./bin/start.php http:start
websocket:
php ./bin/start.php ws:start
console:
php artisan test
crontab:
/config/crontab.php enable 改为 true 开启
migrate:
php migrate.php migrations:generate php migrate.php migrations:migrate
container
use DcrSwoole\Utils\ApplicationContext; ApplicationContext::getContainer(); //或 di();
路由注解和中间件注解
#[RequestMapping(methods: "GET , POST" , path:"/api/json")] #[Middlewares(AuthMiddleware::class , TestMiddleware::class)] public function test() { return 'hello'; }
路由注解 和 中间件注解 以及Inject注解 使用
<?php declare(strict_types=1); namespace App\Controller; use App\Middleware\AuthMiddleware; use App\Middleware\TestMiddleware; use App\Service\TestService; use DcrSwoole\Annotation\Mapping\Middlewares; use DcrSwoole\Annotation\Mapping\RequestMapping; use DI\Attribute\Inject; class MiddlewareController extends Controller { #[Inject] public TestService $testService; #[RequestMapping(methods: "GET , POST", path:"/test/middleware")] #[Middlewares(AuthMiddleware::class, TestMiddleware::class)] public function test() { return 'hello world'; } }
多个中间件注解
use App\Middleware\AuthMiddleware; use App\Middleware\TestMiddleware; use DcrSwoole\Annotation\Mapping\Middlewares; use DcrSwoole\Annotation\Mapping\RequestMapping; #[RequestMapping(methods: "GET , POST", path:"/test/middleware")] #[Middlewares(AuthMiddleware::class, TestMiddleware::class)] public function test(): string { return 'ok'; }
从容器 拿对象 获取 参数
use DcrSwoole\Utils\ApplicationContext; //->all() ->get() ->post() 等方法 ApplicationContext::getContainer()->get(Request::class)->all(); //di()->(Request::class)->all();
redis 操作
use DcrSwoole\Utils\ApplicationContext; ApplicationContext::getContainer()->get(DataRedis::class); //->setex ->get ->del ->setnx 等方法 和predis一致
orm model ,使用和laravel orm一致
<?php declare(strict_types=1); namespace App\Model; use DcrSwoole\DbConnection\Model; /** * Class UserModel * @see https://github.com/illuminate/database * @property int $id * @property string $created_at */ class UserModel extends Model { protected $table = 'user'; }
控制器validate
#[RequestMapping(methods: "GET , POST", path:"/test/test4")] public function test4($request, $response) { $validate = Validation::check($this->request->post ?? [], [ // add rule ['title', 'min', 40], ['freeTime', 'number'], ]); if ($validate->isFail()) { var_dump($validate->getErrors()); var_dump($validate->firstError()); } // $postData = $v->all(); // 原始数据 $safeData = $validate->getSafeData(); // 验证通过的安全数据 return $safeData; }
获取配置 需要use DI\Attribute\Inject
#[Inject] public Config $config; #[RequestMapping(methods: "GET , POST", path:"/test/config")] public function config() { //di()->get(Config::class)->get('app.debug'); return $this->config->get('app.debug'); }
中间件
<?php namespace App\Middleware; use App\Middleware\Contract\MiddlewareInterface; use DcrSwoole\Log\LogBase; use DcrSwoole\Request\Request; class TestMiddleware implements MiddlewareInterface { public function handle() { return static function ($request, $next) { $data = di()->get(Request::class)->get(); // throw new RuntimeException('test middlere error'); return $next->handle($request); }; } }
Console 命令应用 需要在app/Console/Kernel.php
配置 命令类
<?php declare(strict_types=1); namespace App\Console\Command; use App\Repository\TestRepository; use DcrSwoole\Utils\ApplicationContext; use Inhere\Console\IO\Input; use Inhere\Console\IO\Output; use Toolkit\PFlag\FlagsParser; /** * @package app\Console\Command * php artisan test */ class TestCommand extends \Inhere\Console\Command { protected static string $name = 'test'; protected static string $desc = 'print system ENV information'; protected function configFlags(FlagsParser $fs): void { // 绑定选项 $fs->addOptByRule('update, up', 'bool;update linux command docs to latest'); $fs->addOptByRule('init, i', 'bool;update linux command docs to latest'); $fs->addOptByRule('search, s', 'string;input keywords for search'); // 绑定参数 // - 这里没有设置必须 可以不传,获取到就是空string $fs->addArg('keywords', 'the keywords for search or show docs', 'string'); } protected function execute(Input $input, Output $output) { $keywords = $this->flags->getOpt('search', 23); ApplicationContext::getContainer()->get(TestRepository::class)->fromRepos(); $output->info("hello world ..."); } }
crontab定时任务 需要在 /config/crontab.php
配置 定时任务
<?php declare(strict_types=1); namespace App\Crontab; use App\Crontab\Contract\CrontabInterface; use App\Repository\TestRepository; use DcrSwoole\Utils\ApplicationContext; class TestCrontab implements CrontabInterface { public function execute(): void { ApplicationContext::getContainer()->get(TestRepository::class)->test1(); } }
event 事件
<?php namespace App\Event; use Symfony\Contracts\EventDispatcher\Event; class TestEvent extends Event { public const NAME = 'order.placed'; //推荐使用对象 比如模型对象或dto object protected $params; public function __construct($params) { $this->params = $params; } public function getParams() { return $this->params; } }
listener 监听者
<?php namespace App\Listener; use App\Event\TestEvent; use App\Listener\Contract\BaseListenerInterface; class TestEventListener implements BaseListenerInterface { /** * @param TestEvent $event */ public function process(object $event) { echo '打印参数'.PHP_EOL; var_dump($event->getParams()); } }
触发事件
#[RequestMapping(methods: "GET , POST", path:"/test/event")] public function event($request, $response): array { $params = [ 'test' => 23, ]; event(new TestEvent($params),TestEvent::NAME); // 初始化事件分发器 return []; }
或者
#[RequestMapping(methods: "GET , POST", path:"/test/event")] public function event($request, $response): array { $params = [ 'test' => 23, ]; $dispatcher = EventInstance::instance(); $dispatcher->dispatch(new TestEvent($params), TestEvent::NAME); }
切面 aop
<?php namespace App\Aspect; use App\Service\UserService; use Hyperf\Di\Aop\ProceedingJoinPoint; use Hyperf\Di\Exception\Exception; /** * 需要再config/config 文件配置 切面类 */ class DebugAspect { //要切入的方法 public array $classes = [ UserService::class . '::first', ]; /** * 测试切面 * @param ProceedingJoinPoint $proceedingJoinPoint * @return mixed */ public function process(ProceedingJoinPoint $proceedingJoinPoint) { var_dump(11); try { return $proceedingJoinPoint->process(); } catch (Exception $e) { } } }
文档
更多例子查看 代码demo
ab 本机macbook pro 压测 Requests per second: 58832.04 [#/sec] (mean)
→ ab -k -n 100000 -c 30 'http://127.0.0.1:9501/test/request'
This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software: swoole-http-server
Server Hostname: 127.0.0.1
Server Port: 9501
Document Path: /test/request
Document Length: 4 bytes
Concurrency Level: 30
Time taken for tests: 1.700 seconds
Complete requests: 100000
Failed requests: 0
Keep-Alive requests: 100000
Total transferred: 15600000 bytes
HTML transferred: 400000 bytes
Requests per second: 58832.04 [#/sec] (mean)
Time per request: 0.510 [ms] (mean)
Time per request: 0.017 [ms] (mean, across all concurrent requests)
Transfer rate: 8962.69 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 1
Processing: 0 1 0.3 0 15
Waiting: 0 0 0.3 0 15
Total: 0 1 0.3 0 15
ERROR: The median and mean for the processing time are more than twice the standard
deviation apart. These results are NOT reliable.
ERROR: The median and mean for the total time are more than twice the standard
deviation apart. These results are NOT reliable.
Percentage of the requests served within a certain time (ms)
50% 0
66% 1
75% 1
80% 1
90% 1
95% 1
98% 1
99% 2
100% 15 (longest request)
wrk 压测 Requests/sec: 79540.12
→ wrk -t20 -c300 -d 30s --latency http://127.0.0.1:9501/test/request
Running 30s test @ http://127.0.0.1:9501/test/request
20 threads and 300 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 7.56ms 14.05ms 154.35ms 88.96%
Req/Sec 4.71k 1.25k 18.48k 82.37%
Latency Distribution
50% 1.43ms
75% 6.30ms
90% 23.63ms
99% 68.04ms
2394042 requests in 30.10s, 356.17MB read
Socket errors: connect 67, read 86, write 0, timeout 0
Requests/sec: 79540.12
Transfer/sec: 11.83MB
composer依赖组件
"symfony/event-dispatcher": "^6.2", 事件监听 观察者模式
"doctrine/migrations": "^3.5", migrate
"elasticsearch/elasticsearch": "7.16", es
"firebase/php-jwt": "^6.3", jwt token
"gregwar/captcha": "^1.1", captcha
"guanhui07/database": "^1.0", laravel orm 改
"guanhui07/dcr-swoole-crontab": "^1.0", crontab
"guanhui07/guzzle": "^1.0", guzzle client
"guanhui07/redis": "^1.0", redis pool
"inhere/console": "^4.1", console command
"inhere/php-validate": "^2.8", validate 验证器
"intervention/image": "^2.7", image操作
"middlewares/utils": "^3.0", middleware中间件
"monolog/monolog": "^2.8", monolog
"mwangithegreat/faker": "^1.9", faker造数据
"nesbot/carbon": "^2.6", carbon time
"nikic/fast-route": "^1.3", nikic的 resful route
"opis/closure": "^3.6", 闭包序列化
"php-amqplib/php-amqplib": "dev-master", rabbitmq
"php-di/php-di": "^7.0", 依赖注入 di container
"qiniu/php-sdk": "^7.7", 七牛cdn
"spatie/image": "^2.2",
"symfony/finder": "^5.0", symfony finder
"vlucas/phpdotenv": "^5.4" dotenv读取
"hyperf/aop-integration": " ^1.1", aop切面支持
关联
参考 hyperf laravel webman 项目
https://github.com/guanhui07/dcr fpm以及workerman实现websocket
https://github1s.com/walkor/webman-framework
https://github1s.com/hyperf/hyperf
https://github1s.com/laravel/laravel
https://github.com/SerendipitySwow/Serendipity-job
https://github.com/sunsgneayo/annotation 路由注解参考
todo:
类似hyperf
实现 Command Crontab AutoController Cacheable 等注解
我的其他包:
https://github.com/guanhui07/dcr 借鉴Laravel实现的 PHP Framework ,FPM模式、websocket使用的workerman、支持容器、PHP8特性attributes实现了路由注解、中间件注解、Laravel Orm等特性
https://github.com/guanhui07/redis Swoole模式下 Redis连接池
https://github.com/guanhui07/facade facade、门面 fpm模式下可使用
https://github.com/guanhui07/dcr-swoole-crontab 基于swoole实现的crontab秒级定时任务
https://github.com/guanhui07/timer php定时器,参考了workerman源码 实现一个单进程(守护进程)的定时器。
https://github.com/guanhui07/database 基于 illuminate/database 做的连接池用于适配Swoole的协程环境
https://github.com/guanhui07/dcr-swoole 高性能PHP Framework ,Cli模式,基于Swoole实现,常驻内存,协程框架,支持容器、切面、PHP8特性attributes实现了路由注解、中间件注解、支持Laravel Orm等特性
https://github.com/guanhui07/geohash geohash 用于附近的人
https://github.com/guanhui07/open-ai open-ai chatgpt调用