├── README.md ├── src ├── .editorconfig ├── .env ├── .env.example ├── .gitignore ├── .php_cs ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── app │ ├── Boot │ │ └── MyProcess.php │ ├── Breaker │ │ └── UserBreaker.php │ ├── Commands │ │ └── TestCommand.php │ ├── Controllers │ │ ├── Admin │ │ │ └── DemoController.php │ │ ├── Api │ │ │ └── RestController.php │ │ ├── DemoController.php │ │ ├── ExceptionController.php │ │ ├── HttpClientController.php │ │ ├── IndexController.php │ │ ├── MiddlewareController.php │ │ ├── OrmController.php │ │ ├── Psr7Controller.php │ │ ├── RedisController.php │ │ ├── RestController.php │ │ ├── RouteController.php │ │ ├── RpcController.php │ │ ├── SessionController.php │ │ ├── TaskController.php │ │ └── ValidatorController.php │ ├── Exception │ │ └── SwoftExceptionHandler.php │ ├── Fallback │ │ └── DemoServiceFallback.php │ ├── Lib │ │ ├── DemoInterface.php │ │ └── MdDemoInterface.php │ ├── Listener │ │ ├── APPStart.php │ │ └── TaskFinish.php │ ├── Middlewares │ │ ├── ActionTestMiddleware.php │ │ ├── ControllerSubMiddleware.php │ │ ├── ControllerTestMiddleware.php │ │ ├── GroupTestMiddleware.php │ │ ├── ServiceMiddleware.php │ │ ├── ServiceSubMiddleware.php │ │ ├── SubMiddleware.php │ │ └── SubMiddlewares.php │ ├── Models │ │ ├── Dao │ │ │ ├── UserDao.php │ │ │ └── UserExtDao.php │ │ ├── Data │ │ │ ├── UserData.php │ │ │ └── UserExtData.php │ │ ├── Entity │ │ │ ├── Count.php │ │ │ └── User.php │ │ └── Logic │ │ │ ├── IndexLogic.php │ │ │ └── UserLogic.php │ ├── Pool │ │ ├── Config │ │ │ ├── DemoRedisPoolConfig.php │ │ │ └── UserPoolConfig.php │ │ ├── DemoRedisPool.php │ │ └── UserServicePool.php │ ├── Process │ │ └── MyProcess.php │ ├── Services │ │ ├── DemoService.php │ │ ├── DemoServiceV2.php │ │ └── MiddlewareService.php │ ├── Swoft.php │ ├── Tars │ │ └── Manage.php │ ├── Tasks │ │ ├── SyncTask.php │ │ └── TarsKeepAliveTask.php │ └── WebSocket │ │ └── EchoController.php ├── bin │ ├── bootstrap.php │ └── swoft ├── changelog.md ├── composer.json ├── config │ ├── beans │ │ ├── base.php │ │ ├── console.php │ │ ├── log.php │ │ └── service.php │ ├── define.php │ ├── properties │ │ ├── app.php │ │ ├── breaker.php │ │ ├── cache.php │ │ ├── db.php │ │ ├── provider.php │ │ └── service.php │ └── server.php ├── docker-compose.yml ├── index.php ├── phar.build.inc ├── phpunit.xml ├── public │ └── .gitkeep ├── resources │ ├── README.md │ ├── languages │ │ ├── en │ │ │ ├── default.php │ │ │ └── msg.php │ │ └── zh │ │ │ ├── default.php │ │ │ └── msg.php │ └── views │ │ ├── demo │ │ ├── content.php │ │ └── view.php │ │ ├── exception │ │ └── index.php │ │ ├── index │ │ └── index.php │ │ └── layouts │ │ ├── default.php │ │ └── default │ │ ├── footer.php │ │ └── header.php ├── runtime │ ├── logs │ │ └── .gitkeep │ └── uploadfiles │ │ └── .gitkeep └── test │ ├── Cases │ ├── AbstractTestCase.php │ ├── DemoControllerTest.php │ ├── IndexControllerTest.php │ ├── MiddlewareTest.php │ ├── RedisControllerTest.php │ ├── RestTest.php │ ├── RouteTest.php │ └── ValidatorControllerTest.php │ ├── Dockerfile │ ├── README.md │ ├── bootstrap.php │ └── docker-compose.yml └── tars └── tars.proto.php /README.md: -------------------------------------------------------------------------------- 1 | 2 | # 简介 3 | 让swoft框架欢快的跑在tars里面 4 | * 支持打包发布 5 | * 支持服务存活上报(服务注册) 6 | 7 | # 相关项目 8 | 9 | * SWOFT (https://github.com/swoft-cloud/swoft)   10 | * TARSPHP (https://github.com/TarsPHP/TarsPHP) 11 | * TARSPHP DOCKER (https://github.com/tangramor/docker-tars) 12 | 13 | 14 | # 使用 15 | 16 | * Clone 项目 17 | * 安装依赖 `composer install` 18 | * 打包 `composer run-script deploy` 19 | * 上传tars平台 20 | 21 | # 配置说明 22 | 23 | * 服务名需要在 ./tars/tars.proto.php (appName&serverName) 和 ./src/.env (PNAME) 里面正确配置(2个地方要配置正确且一致) 24 | * swoft的端口号不使用tars平台下发的端口号(因为swoft可以支持多端口多协议) 25 | 26 | # 重启问题 27 | * 使用docker-tars,pcre可能没开启。运行php --ri swoole,看是否存在pcre => enabled。不存在运行yum install pcre-devel,再重新编译swoole!! 28 | -------------------------------------------------------------------------------- /src/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | # 对所有文件生效 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | # 对后缀名为 md 的文件生效 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | 16 | [*.php] 17 | indent_size = 4 18 | 19 | [resources/views/*.php] 20 | indent_size = 2 21 | 22 | -------------------------------------------------------------------------------- /src/.env: -------------------------------------------------------------------------------- 1 | # Server 2 | PFILE=/tmp/swoft.pid 3 | PNAME=PHPTest.swoft 4 | TCPABLE=true 5 | CRONABLE=true 6 | AUTO_RELOAD=true 7 | AUTO_REGISTER=false 8 | 9 | # HTTP 10 | HTTP_HOST=0.0.0.0 11 | HTTP_PORT=8011 12 | HTTP_MODE=SWOOLE_PROCESS 13 | HTTP_TYPE=SWOOLE_SOCK_TCP 14 | 15 | # WebSocket 16 | WS_ENABLE_HTTP=true 17 | 18 | # TCP 19 | TCP_HOST=0.0.0.0 20 | TCP_PORT=8099 21 | TCP_MODE=SWOOLE_PROCESS 22 | TCP_TYPE=SWOOLE_SOCK_TCP 23 | TCP_PACKAGE_MAX_LENGTH=2048 24 | TCP_OPEN_EOF_CHECK=false 25 | 26 | # Crontab 27 | CRONTAB_TASK_COUNT=1024 28 | CRONTAB_TASK_QUEUE=2048 29 | 30 | # Swoole Settings 31 | WORKER_NUM=1 32 | MAX_REQUEST=100000 33 | DAEMONIZE=0 34 | DISPATCH_MODE=2 35 | TASK_IPC_MODE=2 36 | MESSAGE_QUEUE_KEY=1879052289 37 | TASK_TMPDIR=/tmp/ 38 | LOG_FILE=@runtime/logs/swoole.log 39 | TASK_WORKER_NUM=1 40 | PACKAGE_MAX_LENGTH=2048 41 | OPEN_HTTP2_PROTOCOL=false 42 | SSL_CERT_FILE=/path/to/ssl_cert_file 43 | SSL_KEY_FILE=/path/to/ssl_key_file 44 | 45 | # Database Master nodes 46 | DB_NAME=dbMaster 47 | DB_URI=127.0.0.1:3306/test?user=root&password=123456&charset=utf8,127.0.0.1:3306/test?user=root&password=123456&charset=utf8 48 | DB_MIN_ACTIVE=5 49 | DB_MAX_ACTIVE=10 50 | DB_MAX_WAIT=20 51 | DB_MAX_WAIT_TIME=3 52 | DB_MAX_IDLE_TIME=60 53 | DB_TIMEOUT=2 54 | 55 | # Database Slave nodes 56 | DB_SLAVE_NAME=dbSlave 57 | DB_SLAVE_URI=127.0.0.1:3306/test?user=root&password=123456&charset=utf8,127.0.0.1:3306/test?user=root&password=123456&charset=utf8 58 | DB_SLAVE_MIN_ACTIVE=5 59 | DB_SLAVE_MAX_ACTIVE=10 60 | DB_SLAVE_MAX_WAIT=20 61 | DB_SLAVE_MAX_WAIT_TIME=3 62 | DB_SLAVE_MAX_IDLE_TIME=60 63 | DB_SLAVE_TIMEOUT=3 64 | 65 | # Redis 66 | REDIS_NAME=redis 67 | REDIS_DB=2 68 | REDIS_URI=127.0.0.1:6379,127.0.0.1:6379 69 | REDIS_MIN_ACTIVE=5 70 | REDIS_MAX_ACTIVE=10 71 | REDIS_MAX_WAIT=20 72 | REDIS_MAX_WAIT_TIME=3 73 | REDIS_MAX_IDLE_TIME=60 74 | REDIS_TIMEOUT=3 75 | REDIS_SERIALIZE=1 76 | 77 | # other redis node 78 | REDIS_DEMO_REDIS_DB=6 79 | REDIS_DEMO_REDIS_PREFIX=demo_redis_ 80 | 81 | # User service (demo service) 82 | USER_POOL_NAME=user 83 | USER_POOL_URI=127.0.0.1:8099,127.0.0.1:8099 84 | USER_POOL_MIN_ACTIVE=5 85 | USER_POOL_MAX_ACTIVE=10 86 | USER_POOL_MAX_WAIT=20 87 | USER_POOL_TIMEOUT=200 88 | USER_POOL_MAX_WAIT_TIME=3 89 | USER_POOL_MAX_IDLE_TIME=60 90 | USER_POOL_USE_PROVIDER=false 91 | USER_POOL_BALANCER=random 92 | USER_POOL_PROVIDER=consul 93 | 94 | # User service breaker (demo service) 95 | USER_BREAKER_FAIL_COUNT = 3 96 | USER_BREAKER_SUCCESS_COUNT = 6 97 | USER_BREAKER_DELAY_TIME = 5000 98 | 99 | # Consul 100 | CONSUL_ADDRESS=http://127.0.0.1 101 | CONSUL_PORT=8500 102 | CONSUL_REGISTER_NAME=user 103 | CONSUL_REGISTER_ETO=false 104 | CONSUL_REGISTER_SERVICE_ADDRESS=127.0.0.1 105 | CONSUL_REGISTER_SERVICE_PORT=8099 106 | CONSUL_REGISTER_CHECK_NAME=user 107 | CONSUL_REGISTER_CHECK_TCP=127.0.0.1:8099 108 | CONSUL_REGISTER_CHECK_INTERVAL=10 109 | CONSUL_REGISTER_CHECK_TIMEOUT=1 110 | -------------------------------------------------------------------------------- /src/.env.example: -------------------------------------------------------------------------------- 1 | # Server 2 | PFILE=/tmp/swoft.pid 3 | PNAME=php-swoft 4 | TCPABLE=true 5 | CRONABLE=false 6 | AUTO_RELOAD=true 7 | AUTO_REGISTER=false 8 | 9 | # HTTP 10 | HTTP_HOST=0.0.0.0 11 | HTTP_PORT=80 12 | HTTP_MODE=SWOOLE_PROCESS 13 | HTTP_TYPE=SWOOLE_SOCK_TCP 14 | 15 | # WebSocket 16 | WS_ENABLE_HTTP=true 17 | 18 | # TCP 19 | TCP_HOST=0.0.0.0 20 | TCP_PORT=8099 21 | TCP_MODE=SWOOLE_PROCESS 22 | TCP_TYPE=SWOOLE_SOCK_TCP 23 | TCP_PACKAGE_MAX_LENGTH=2048 24 | TCP_OPEN_EOF_CHECK=false 25 | 26 | # Crontab 27 | CRONTAB_TASK_COUNT=1024 28 | CRONTAB_TASK_QUEUE=2048 29 | 30 | # Swoole Settings 31 | WORKER_NUM=1 32 | MAX_REQUEST=100000 33 | DAEMONIZE=0 34 | DISPATCH_MODE=2 35 | TASK_IPC_MODE=2 36 | MESSAGE_QUEUE_KEY=1879052289 37 | TASK_TMPDIR=/tmp/ 38 | LOG_FILE=@runtime/logs/swoole.log 39 | TASK_WORKER_NUM=1 40 | PACKAGE_MAX_LENGTH=2048 41 | OPEN_HTTP2_PROTOCOL=false 42 | SSL_CERT_FILE=/path/to/ssl_cert_file 43 | SSL_KEY_FILE=/path/to/ssl_key_file 44 | 45 | # Database Master nodes 46 | DB_NAME=dbMaster 47 | DB_URI=127.0.0.1:3306/test?user=root&password=123456&charset=utf8,127.0.0.1:3306/test?user=root&password=123456&charset=utf8 48 | DB_MIN_ACTIVE=5 49 | DB_MAX_ACTIVE=10 50 | DB_MAX_WAIT=20 51 | DB_MAX_WAIT_TIME=3 52 | DB_MAX_IDLE_TIME=60 53 | DB_TIMEOUT=2 54 | 55 | # Database Slave nodes 56 | DB_SLAVE_NAME=dbSlave 57 | DB_SLAVE_URI=127.0.0.1:3306/test?user=root&password=123456&charset=utf8,127.0.0.1:3306/test?user=root&password=123456&charset=utf8 58 | DB_SLAVE_MIN_ACTIVE=5 59 | DB_SLAVE_MAX_ACTIVE=10 60 | DB_SLAVE_MAX_WAIT=20 61 | DB_SLAVE_MAX_WAIT_TIME=3 62 | DB_SLAVE_MAX_IDLE_TIME=60 63 | DB_SLAVE_TIMEOUT=3 64 | 65 | # Redis 66 | REDIS_NAME=redis 67 | REDIS_DB=2 68 | REDIS_URI=127.0.0.1:6379,127.0.0.1:6379 69 | REDIS_MIN_ACTIVE=5 70 | REDIS_MAX_ACTIVE=10 71 | REDIS_MAX_WAIT=20 72 | REDIS_MAX_WAIT_TIME=3 73 | REDIS_MAX_IDLE_TIME=60 74 | REDIS_TIMEOUT=3 75 | REDIS_SERIALIZE=1 76 | 77 | # other redis node 78 | REDIS_DEMO_REDIS_DB=6 79 | REDIS_DEMO_REDIS_PREFIX=demo_redis_ 80 | 81 | # User service (demo service) 82 | USER_POOL_NAME=user 83 | USER_POOL_URI=127.0.0.1:8099,127.0.0.1:8099 84 | USER_POOL_MIN_ACTIVE=5 85 | USER_POOL_MAX_ACTIVE=10 86 | USER_POOL_MAX_WAIT=20 87 | USER_POOL_TIMEOUT=200 88 | USER_POOL_MAX_WAIT_TIME=3 89 | USER_POOL_MAX_IDLE_TIME=60 90 | USER_POOL_USE_PROVIDER=false 91 | USER_POOL_BALANCER=random 92 | USER_POOL_PROVIDER=consul 93 | 94 | # User service breaker (demo service) 95 | USER_BREAKER_FAIL_COUNT = 3 96 | USER_BREAKER_SUCCESS_COUNT = 6 97 | USER_BREAKER_DELAY_TIME = 5000 98 | 99 | # Consul 100 | CONSUL_ADDRESS=http://127.0.0.1 101 | CONSUL_PORT=8500 102 | CONSUL_REGISTER_NAME=user 103 | CONSUL_REGISTER_ETO=false 104 | CONSUL_REGISTER_SERVICE_ADDRESS=127.0.0.1 105 | CONSUL_REGISTER_SERVICE_PORT=8099 106 | CONSUL_REGISTER_CHECK_NAME=user 107 | CONSUL_REGISTER_CHECK_TCP=127.0.0.1:8099 108 | CONSUL_REGISTER_CHECK_INTERVAL=10 109 | CONSUL_REGISTER_CHECK_TIMEOUT=1 110 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | .buildpath 2 | .settings/ 3 | .project 4 | *.patch 5 | .idea/ 6 | .git/ 7 | runtime/ 8 | vendor/ 9 | temp/ 10 | *.lock 11 | .phpintel/ 12 | .env 13 | .DS_Store -------------------------------------------------------------------------------- /src/.php_cs: -------------------------------------------------------------------------------- 1 | setRiskyAllowed(true) 14 | ->setRules([ 15 | '@PSR2' => true, 16 | 'header_comment' => [ 17 | 'commentType' => 'PHPDoc', 18 | 'header' => $header, 19 | 'separate' => 'none' 20 | ], 21 | 'array_syntax' => [ 22 | 'syntax' => 'short' 23 | ], 24 | 'single_quote' => true, 25 | 'class_attributes_separation' => true, 26 | 'no_unused_imports' => true, 27 | 'standardize_not_equals' => true, 28 | ]) 29 | ->setFinder( 30 | PhpCsFixer\Finder::create() 31 | ->exclude('public') 32 | ->exclude('resources') 33 | ->exclude('config') 34 | ->exclude('runtime') 35 | ->exclude('vendor') 36 | ->in(__DIR__) 37 | ) 38 | ->setUsingCache(false); 39 | -------------------------------------------------------------------------------- /src/.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.0 5 | - 7.1 6 | - 7.2 7 | 8 | install: 9 | - wget https://github.com/redis/hiredis/archive/v0.13.3.tar.gz -O hiredis.tar.gz && mkdir -p hiredis && tar -xf hiredis.tar.gz -C hiredis --strip-components=1 && cd hiredis && sudo make -j$(nproc) && sudo make install && sudo ldconfig && cd .. 10 | - pecl install -f swoole-2.0.12 11 | before_script: 12 | - composer update --dev 13 | 14 | script: composer test 15 | -------------------------------------------------------------------------------- /src/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.1 2 | 3 | MAINTAINER huangzhhui 4 | 5 | RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ 6 | && echo 'Asia/Shanghai' > /etc/timezone 7 | 8 | RUN apt-get update \ 9 | && apt-get install -y \ 10 | curl \ 11 | wget \ 12 | git \ 13 | zip \ 14 | libz-dev \ 15 | libssl-dev \ 16 | libnghttp2-dev \ 17 | && apt-get clean \ 18 | && apt-get autoremove 19 | 20 | RUN curl -sS https://getcomposer.org/installer | php \ 21 | && mv composer.phar /usr/local/bin/composer \ 22 | && composer self-update --clean-backups 23 | 24 | RUN pecl install redis && docker-php-ext-enable redis && pecl clear-cache 25 | 26 | RUN docker-php-ext-install pdo_mysql 27 | 28 | RUN wget https://github.com/redis/hiredis/archive/v0.13.3.tar.gz -O hiredis.tar.gz \ 29 | && mkdir -p hiredis \ 30 | && tar -xf hiredis.tar.gz -C hiredis --strip-components=1 \ 31 | && rm hiredis.tar.gz \ 32 | && ( \ 33 | cd hiredis \ 34 | && make -j$(nproc) \ 35 | && make install \ 36 | && ldconfig \ 37 | ) \ 38 | && rm -r hiredis 39 | 40 | RUN wget https://github.com/swoole/swoole-src/archive/v2.1.1.tar.gz -O swoole.tar.gz \ 41 | && mkdir -p swoole \ 42 | && tar -xf swoole.tar.gz -C swoole --strip-components=1 \ 43 | && rm swoole.tar.gz \ 44 | && ( \ 45 | cd swoole \ 46 | && phpize \ 47 | && ./configure --enable-async-redis --enable-mysqlnd --enable-coroutine --enable-openssl --enable-http2 \ 48 | && make -j$(nproc) \ 49 | && make install \ 50 | ) \ 51 | && rm -r swoole \ 52 | && docker-php-ext-enable swoole 53 | 54 | ADD . /var/www/swoft 55 | 56 | WORKDIR /var/www/swoft 57 | RUN composer install --no-dev \ 58 | && composer dump-autoload -o \ 59 | && composer clearcache 60 | 61 | EXPOSE 80 62 | 63 | CMD ["php", "/var/www/swoft/bin/swoft", "start"] 64 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 |

2 |     3 | swoft 4 | 5 |

6 | 7 | [![Latest Version](https://img.shields.io/badge/beta-v1.0.0-green.svg?maxAge=2592000)](https://github.com/swoft-cloud/swoft/releases) 8 | [![Build Status](https://travis-ci.org/swoft-cloud/swoft.svg?branch=master)](https://travis-ci.org/swoft-cloud/swoft) 9 | [![Php Version](https://img.shields.io/badge/php-%3E=7.0-brightgreen.svg?maxAge=2592000)](https://secure.php.net/) 10 | [![Swoole Version](https://img.shields.io/badge/swoole-%3E=2.1.1-brightgreen.svg?maxAge=2592000)](https://github.com/swoole/swoole-src) 11 | [![Hiredis Version](https://img.shields.io/badge/hiredis-%3E=0.1-brightgreen.svg?maxAge=2592000)](https://github.com/redis/hiredis) 12 | [![Swoft Doc](https://img.shields.io/badge/docs-passing-green.svg?maxAge=2592000)](https://doc.swoft.org) 13 | [![Swoft License](https://img.shields.io/hexpm/l/plug.svg?maxAge=2592000)](https://github.com/swoft-cloud/swoft/blob/master/LICENSE) 14 | 15 | 16 | # 简介 17 | 首个基于 Swoole 原生协程的新时代 PHP 高性能协程全栈组件化框架,内置协程网络服务器及常用的协程客户端,常驻内存,不依赖传统的 PHP-FPM,全异步非阻塞 IO 实现,以类似于同步客户端的写法实现异步客户端的使用,没有复杂的异步回调,没有繁琐的 yield,有类似 Go 语言的协程、灵活的注解、强大的全局依赖注入容器、完善的服务治理、灵活强大的 AOP、标准的 PSR 规范实现等等,可以用于构建高性能的Web系统、API、中间件、基础服务等等。 18 | 19 | - 基于 Swoole 扩展 20 | - 内置协程 HTTP, TCP, WebSocket 网络服务器 21 | - 强大的 AOP (面向切面编程) 22 | - 灵活完善的注解功能 23 | - 全局的依赖注入容器 24 | - 基于 PSR-7 的 HTTP 消息实现 25 | - 基于 PSR-14 的事件管理器 26 | - 基于 PSR-15 的中间件 27 | - 基于 PSR-16 的缓存设计 28 | - 可扩展的高性能 RPC 29 | - 完善的服务治理,熔断,降级,负载,注册与发现 30 | - 数据库 ORM 31 | - 通用连接池 32 | - 协程 Mysql, Redis, RPC, HTTP 客户端 33 | - 协程和同步阻塞客户端无缝自动切换 34 | - 协程、异步任务投递 35 | - 自定义用户进程 36 | - RESTful 支持 37 | - 国际化(i18n)支持 38 | - 高性能路由 39 | - 快速灵活的参数验证器 40 | - 别名机制 41 | - 强大的日志系统 42 | - 跨平台热更新自动 Reload 43 | 44 | 45 | # 文档 46 | [**中文文档**](https://doc.swoft.org) 47 | 48 | QQ 交流群: 548173319 49 | 50 | # 环境要求 51 | 52 | 1. PHP 7.0 + 53 | 2. [Swoole 2.1.1](https://github.com/swoole/swoole-src/releases) +, 需开启协程和异步Redis 54 | 3. [Hiredis](https://github.com/redis/hiredis/releases) 55 | 4. [Composer](https://getcomposer.org/) 56 | 57 | # 安装 58 | 59 | ## 手动安装 60 | 61 | * Clone 项目 62 | * 安装依赖 `composer install` 63 | 64 | ## Composer 安装 65 | 66 | * `composer create-project swoft/swoft swoft` 67 | 68 | ## Docker 安装 69 | 70 | * `docker run -p 80:80 swoft/swoft` 71 | 72 | ## Docker-Compose 安装 73 | 74 | * `cd swoft` 75 | * `docker-compose up` 76 | 77 | # 配置 78 | 79 | 若在执行 `composer install` 的时候由程序自动复制环境变量配置文件失败,则可手动复制项目根目录的 `.env.example` 并命名为 `.env`,注意在执行 `composer update` 时并不会触发相关的复制操作 80 | 81 | ``` 82 | # Server 83 | PFILE=/tmp/swoft.pid 84 | PNAME=php-swoft 85 | TCPABLE=true 86 | CRONABLE=false 87 | AUTO_RELOAD=true 88 | 89 | # HTTP 90 | HTTP_HOST=0.0.0.0 91 | HTTP_PORT=80 92 | 93 | # WebSocket 94 | WS_ENABLE_HTTP=true 95 | 96 | # TCP 97 | TCP_HOST=0.0.0.0 98 | TCP_PORT=8099 99 | TCP_PACKAGE_MAX_LENGTH=2048 100 | TCP_OPEN_EOF_CHECK=false 101 | 102 | # Crontab 103 | CRONTAB_TASK_COUNT=1024 104 | CRONTAB_TASK_QUEUE=2048 105 | 106 | # Settings 107 | WORKER_NUM=1 108 | MAX_REQUEST=10000 109 | DAEMONIZE=0 110 | DISPATCH_MODE=2 111 | LOG_FILE=@runtime/swoole.log 112 | TASK_WORKER_NUM=1 113 | ``` 114 | 115 | ## 管理 116 | 117 | ### 帮助命令 118 | 119 | ```text 120 | [root@swoft]# php bin/swoft -h 121 | ____ __ _ 122 | / ___|_ _____ / _| |_ 123 | \___ \ \ /\ / / _ \| |_| __| 124 | ___) \ V V / (_) | _| |_ 125 | |____/ \_/\_/ \___/|_| \__| 126 | 127 | Usage: 128 | php bin/swoft {command} [arguments ...] [options ...] 129 | 130 | Commands: 131 | entity The group command list of database entity 132 | gen Generate some common application template classes 133 | rpc The group command list of rpc server 134 | server The group command list of http-server 135 | ws There some commands for manage the webSocket server 136 | 137 | Options: 138 | -v, --version show version 139 | -h, --help show help 140 | ``` 141 | 142 | ## HTTP Server启动 143 | 144 | > 是否同时启动RPC服务器取决于.env文件配置 145 | 146 | ```bash 147 | // 启动服务,根据 .env 配置决定是否是守护进程 148 | php bin/swoft start 149 | 150 | // 守护进程启动,覆盖 .env 守护进程(DAEMONIZE)的配置 151 | php bin/swoft start -d 152 | 153 | // 重启 154 | php bin/swoft restart 155 | 156 | // 重新加载 157 | php bin/swoft reload 158 | 159 | // 关闭服务 160 | php bin/swoft stop 161 | ``` 162 | 163 | ### WebSocket Server启动 164 | 165 | 启动WebSocket服务器,可选是否同时支持http处理 166 | 167 | ```bash 168 | // 启动服务,根据 .env 配置决定是否是守护进程 169 | php bin/swoft ws:start 170 | 171 | // 守护进程启动,覆盖 .env 守护进程(DAEMONIZE)的配置 172 | php bin/swoft ws:start -d 173 | 174 | // 重启 175 | php bin/swoft ws:restart 176 | 177 | // 重新加载 178 | php bin/swoft ws:reload 179 | 180 | // 关闭服务 181 | php bin/swoft ws:stop 182 | ``` 183 | 184 | ## RPC Server启动 185 | 186 | > 启动独立的RPC服务器 187 | 188 | ```bash 189 | // 启动服务,根据 .env 配置决定是否是守护进程 190 | php bin/swoft rpc:start 191 | 192 | // 守护进程启动,覆盖 .env 守护进程(DAEMONIZE)的配置 193 | php bin/swoft rpc:start -d 194 | 195 | // 重启 196 | php bin/swoft rpc:restart 197 | 198 | // 重新加载 199 | php bin/swoft rpc:reload 200 | 201 | // 关闭服务 202 | php bin/swoft rpc:stop 203 | 204 | ``` 205 | 206 | # 更新日志 207 | 208 | [更新日志](changelog.md) 209 | 210 | # 协议 211 | Swoft 的开源协议为 Apache-2.0,详情参见[LICENSE](LICENSE) 212 | -------------------------------------------------------------------------------- /src/app/Boot/MyProcess.php: -------------------------------------------------------------------------------- 1 | getPname(); 30 | $processName = "$pname myProcess process"; 31 | $process->name($processName); 32 | 33 | echo "Custom boot process \n"; 34 | 35 | $result = Task::deliverByProcess('sync', 'deliverCo', ['p', 'p2']); 36 | var_dump($result); 37 | 38 | ProcessBuilder::create('customProcess')->start(); 39 | } 40 | 41 | public function check(): bool 42 | { 43 | return true; 44 | } 45 | } -------------------------------------------------------------------------------- /src/app/Breaker/UserBreaker.php: -------------------------------------------------------------------------------- 1 | hasOpt('o'); 82 | $opt = input()->getOpt('o'); 83 | $name = input()->getArg('arg', 'swoft'); 84 | 85 | App::trace('this is command log'); 86 | Log::info('this is comamnd info log'); 87 | /* @var UserLogic $logic */ 88 | $logic = App::getBean(UserLogic::class); 89 | $data = $logic->getUserInfo(['uid1']); 90 | var_dump($hasOpt, $opt, $name, $data); 91 | } 92 | 93 | /** 94 | * this task command 95 | * 96 | * @Usage 97 | * test:{command} [arguments] [options] 98 | * 99 | * @Options 100 | * -o,--o this is command option 101 | * 102 | * @Arguments 103 | * arg this is argument 104 | * 105 | * @Example 106 | * php swoft test:task 107 | * 108 | * @Mapping() 109 | */ 110 | public function task() 111 | { 112 | $result = Task::deliver('sync', 'console', ['console']); 113 | var_dump($result); 114 | } 115 | } -------------------------------------------------------------------------------- /src/app/Controllers/Admin/DemoController.php: -------------------------------------------------------------------------------- 1 | query(); 72 | // 获取name参数默认值defaultName 73 | $getName = $request->query('name', 'defaultName'); 74 | // 获取所有POST参数 75 | $post = $request->post(); 76 | // 获取name参数默认值defaultName 77 | $postName = $request->post('name', 'defaultName'); 78 | // 获取所有参,包括GET或POST 79 | $inputs = $request->input(); 80 | // 获取name参数默认值defaultName 81 | $inputName = $request->input('name', 'defaultName'); 82 | 83 | return compact('get', 'getName', 'post', 'postName', 'inputs', 'inputName'); 84 | } 85 | 86 | /** 87 | * 定义一个route,支持get,以"/"开头的定义,直接是根路径,处理uri=/index2. 88 | * 89 | * @RequestMapping(route="/index2", method=RequestMethod::GET) 90 | */ 91 | public function index2() 92 | { 93 | Coroutine::create(function () { 94 | App::trace('this is child trace' . Coroutine::id()); 95 | Coroutine::create(function () { 96 | App::trace('this is child child trace' . Coroutine::id()); 97 | }); 98 | }); 99 | 100 | return 'success'; 101 | } 102 | 103 | /** 104 | * 没有使用注解,自动解析注入,默认支持get和post. 105 | */ 106 | public function task() 107 | { 108 | $result = Task::deliver('test', 'corTask', ['params1', 'params2'], Task::TYPE_CO); 109 | $mysql = Task::deliver('test', 'testMysql', [], Task::TYPE_CO); 110 | $http = Task::deliver('test', 'testHttp', [], Task::TYPE_CO, 20); 111 | $rpc = Task::deliver('test', 'testRpc', [], Task::TYPE_CO, 5); 112 | $result1 = Task::deliver('test', 'asyncTask', [], Task::TYPE_ASYNC); 113 | 114 | return [$rpc, $http, $mysql, $result, $result1]; 115 | } 116 | 117 | public function index6() 118 | { 119 | throw new Exception('AAAA'); 120 | // $a = $b; 121 | $A = new AAA(); 122 | 123 | return ['data6']; 124 | } 125 | 126 | /** 127 | * 子协程测试. 128 | */ 129 | public function cor() 130 | { 131 | // 创建子协程 132 | Coroutine::create(function () { 133 | App::error('child cor error msg'); 134 | App::trace('child cor error msg'); 135 | }); 136 | 137 | // 当前协程id 138 | $cid = Coroutine::id(); 139 | 140 | // 当前运行上下文ID, 协程环境中,顶层协程ID; 任务中,当前任务taskid; 自定义进程中,当前进程ID(pid) 141 | $tid = Coroutine::tid(); 142 | 143 | return [$cid, $tid]; 144 | } 145 | 146 | /** 147 | * 国际化测试. 148 | */ 149 | public function i18n() 150 | { 151 | $data[] = translate('title', [], 'zh'); 152 | $data[] = translate('title', [], 'en'); 153 | $data[] = translate('msg.body', ['stelin', 999], 'en'); 154 | $data[] = translate('msg.body', ['stelin', 666], 'en'); 155 | 156 | return $data; 157 | } 158 | 159 | /** 160 | * 视图渲染demo - 没有使用布局文件. 161 | * 162 | * @RequestMapping() 163 | * @View(template="demo/view") 164 | */ 165 | public function view() 166 | { 167 | $data = [ 168 | 'name' => 'Swoft', 169 | 'repo' => 'https://github.com/swoft-cloud/swoft', 170 | 'doc' => 'https://doc.swoft.org/', 171 | 'doc1' => 'https://swoft-cloud.github.io/swoft-doc/', 172 | 'method' => __METHOD__, 173 | ]; 174 | 175 | return $data; 176 | } 177 | 178 | /** 179 | * 视图渲染demo - 使用布局文件. 180 | * 181 | * @RequestMapping() 182 | * @View(template="demo/content", layout="layouts/default.php") 183 | */ 184 | public function layout() 185 | { 186 | $layout = 'layouts/default.php'; 187 | $data = [ 188 | 'name' => 'Swoft', 189 | 'repo' => 'https://github.com/swoft-cloud/swoft', 190 | 'doc' => 'https://doc.swoft.org/', 191 | 'doc1' => 'https://swoft-cloud.github.io/swoft-doc/', 192 | 'method' => __METHOD__, 193 | 'layoutFile' => $layout, 194 | ]; 195 | 196 | return $data; 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/app/Controllers/Api/RestController.php: -------------------------------------------------------------------------------- 1 | input('name'); 49 | 50 | $bodyParams = $request->getBodyParams(); 51 | $bodyParams = empty($bodyParams) ? ['create', $name] : $bodyParams; 52 | 53 | return $bodyParams; 54 | } 55 | 56 | /** 57 | * 查询一个用户信息 58 | * 地址:/api/user/6. 59 | * 60 | * @RequestMapping(route="{uid}", method={RequestMethod::GET}) 61 | * 62 | * @param int $uid 63 | * 64 | * @return array 65 | */ 66 | public function getUser(int $uid) 67 | { 68 | return ['getUser', $uid]; 69 | } 70 | 71 | /** 72 | * 查询用户的书籍信息 73 | * 地址:/api/user/6/book/8. 74 | * 75 | * @RequestMapping(route="{userId}/book/{bookId}", method={RequestMethod::GET}) 76 | * 77 | * @param int $userId 78 | * @param string $bookId 79 | * 80 | * @return array 81 | */ 82 | public function getBookFromUser(int $userId, string $bookId) 83 | { 84 | return ['bookFromUser', $userId, $bookId]; 85 | } 86 | 87 | /** 88 | * 删除一个用户信息 89 | * 地址:/api/user/6. 90 | * 91 | * @RequestMapping(route="{uid}", method={RequestMethod::DELETE}) 92 | * 93 | * @param int $uid 94 | * 95 | * @return array 96 | */ 97 | public function deleteUser(int $uid) 98 | { 99 | return ['delete', $uid]; 100 | } 101 | 102 | /** 103 | * 更新一个用户信息 104 | * 地址:/api/user/6. 105 | * 106 | * @RequestMapping(route="{uid}", method={RequestMethod::PUT, RequestMethod::PATCH}) 107 | * 108 | * @param int $uid 109 | * @param Request $request 110 | * 111 | * @return array 112 | */ 113 | public function updateUser(Request $request, int $uid) 114 | { 115 | $body = $request->getBodyParams(); 116 | $body['update'] = 'update'; 117 | $body['uid'] = $uid; 118 | 119 | return $body; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/app/Controllers/DemoController.php: -------------------------------------------------------------------------------- 1 | query(); 72 | // 获取name参数默认值defaultName 73 | $getName = $request->query('name', 'defaultName'); 74 | // 获取所有POST参数 75 | $post = $request->post(); 76 | // 获取name参数默认值defaultName 77 | $postName = $request->post('name', 'defaultName'); 78 | // 获取所有参,包括GET或POST 79 | $inputs = $request->input(); 80 | // 获取name参数默认值defaultName 81 | $inputName = $request->input('name', 'defaultName'); 82 | 83 | return compact('get', 'getName', 'post', 'postName', 'inputs', 'inputName'); 84 | } 85 | 86 | /** 87 | * 定义一个route,支持get,以"/"开头的定义,直接是根路径,处理uri=/index2 88 | * @RequestMapping(route="/index2", method=RequestMethod::GET) 89 | */ 90 | public function index2() 91 | { 92 | Coroutine::create(function () { 93 | App::trace('this is child trace' . Coroutine::id()); 94 | Coroutine::create(function () { 95 | App::trace('this is child child trace' . Coroutine::id()); 96 | }); 97 | }); 98 | 99 | return 'success'; 100 | } 101 | 102 | /** 103 | * 没有使用注解,自动解析注入,默认支持get和post 104 | */ 105 | public function task() 106 | { 107 | $result = Task::deliver('test', 'corTask', ['params1', 'params2'], Task::TYPE_CO); 108 | $mysql = Task::deliver('test', 'testMysql', [], Task::TYPE_CO); 109 | $http = Task::deliver('test', 'testHttp', [], Task::TYPE_CO, 20); 110 | $rpc = Task::deliver('test', 'testRpc', [], Task::TYPE_CO, 5); 111 | $result1 = Task::deliver('test', 'asyncTask', [], Task::TYPE_ASYNC); 112 | 113 | return [$rpc, $http, $mysql, $result, $result1]; 114 | } 115 | 116 | public function index6() 117 | { 118 | throw new Exception('AAAA'); 119 | // $a = $b; 120 | $A = new AAA(); 121 | 122 | return ['data6']; 123 | } 124 | 125 | /** 126 | * 子协程测试 127 | */ 128 | public function cor() 129 | { 130 | // 创建子协程 131 | Coroutine::create(function () { 132 | App::error('child cor error msg'); 133 | App::trace('child cor error msg'); 134 | }); 135 | 136 | // 当前协程id 137 | $cid = Coroutine::id(); 138 | 139 | // 当前运行上下文ID, 协程环境中,顶层协程ID; 任务中,当前任务taskid; 自定义进程中,当前进程ID(pid) 140 | $tid = Coroutine::tid(); 141 | 142 | return [$cid, $tid]; 143 | } 144 | 145 | /** 146 | * 国际化测试 147 | */ 148 | public function i18n() 149 | { 150 | $data[] = translate('title', [], 'zh'); 151 | $data[] = translate('title', [], 'en'); 152 | $data[] = translate('msg.body', ['stelin', 999], 'en'); 153 | $data[] = translate('msg.body', ['stelin', 666], 'en'); 154 | 155 | return $data; 156 | } 157 | 158 | /** 159 | * 视图渲染demo - 没有使用布局文件 160 | * @RequestMapping() 161 | * @View(template="demo/view") 162 | */ 163 | public function view() 164 | { 165 | $data = [ 166 | 'name' => 'Swoft', 167 | 'repo' => 'https://github.com/swoft-cloud/swoft', 168 | 'doc' => 'https://doc.swoft.org/', 169 | 'doc1' => 'https://swoft-cloud.github.io/swoft-doc/', 170 | 'method' => __METHOD__, 171 | ]; 172 | 173 | return $data; 174 | } 175 | 176 | /** 177 | * 视图渲染demo - 使用布局文件 178 | * @RequestMapping() 179 | * @View(template="demo/content", layout="layouts/default.php") 180 | */ 181 | public function layout() 182 | { 183 | $layout = 'layouts/default.php'; 184 | $data = [ 185 | 'name' => 'Swoft', 186 | 'repo' => 'https://github.com/swoft-cloud/swoft', 187 | 'doc' => 'https://doc.swoft.org/', 188 | 'doc1' => 'https://swoft-cloud.github.io/swoft-doc/', 189 | 'method' => __METHOD__, 190 | 'layoutFile' => $layout, 191 | ]; 192 | 193 | return $data; 194 | } 195 | 196 | } 197 | -------------------------------------------------------------------------------- /src/app/Controllers/ExceptionController.php: -------------------------------------------------------------------------------- 1 | get('http://www.swoft.org')->getResult(); 31 | $result2 = $client->get('http://www.swoft.org')->getResponse()->getBody()->getContents(); 32 | return compact('result', 'result2'); 33 | } 34 | } -------------------------------------------------------------------------------- /src/app/Controllers/IndexController.php: -------------------------------------------------------------------------------- 1 | 'Home', 45 | 'link' => 'http://www.swoft.org', 46 | ], 47 | [ 48 | 'name' => 'Documentation', 49 | 'link' => 'http://doc.swoft.org', 50 | ], 51 | [ 52 | 'name' => 'Case', 53 | 'link' => 'http://swoft.org/case', 54 | ], 55 | [ 56 | 'name' => 'Issue', 57 | 'link' => 'https://github.com/swoft-cloud/swoft/issues', 58 | ], 59 | [ 60 | 'name' => 'GitHub', 61 | 'link' => 'https://github.com/swoft-cloud/swoft', 62 | ], 63 | ]; 64 | // 返回一个 array 或 Arrayable 对象,Response 将根据 Request Header 的 Accept 来返回数据,目前支持 View, Json, Raw 65 | return compact('name', 'notes', 'links'); 66 | } 67 | 68 | /** 69 | * show view by view function 70 | */ 71 | public function templateView(): Response 72 | { 73 | $name = 'Swoft View'; 74 | $notes = [ 75 | 'New Generation of PHP Framework', 76 | 'Hign Performance, Coroutine and Full Stack' 77 | ]; 78 | $links = [ 79 | [ 80 | 'name' => 'Home', 81 | 'link' => 'http://www.swoft.org', 82 | ], 83 | [ 84 | 'name' => 'Documentation', 85 | 'link' => 'http://doc.swoft.org', 86 | ], 87 | [ 88 | 'name' => 'Case', 89 | 'link' => 'http://swoft.org/case', 90 | ], 91 | [ 92 | 'name' => 'Issue', 93 | 'link' => 'https://github.com/swoft-cloud/swoft/issues', 94 | ], 95 | [ 96 | 'name' => 'GitHub', 97 | 'link' => 'https://github.com/swoft-cloud/swoft', 98 | ], 99 | ]; 100 | $data = compact('name', 'notes', 'links'); 101 | 102 | return view('index/index', $data); 103 | } 104 | 105 | /** 106 | * @RequestMapping() 107 | * @View(template="index/index") 108 | * @return \Swoft\Contract\Arrayable|__anonymous@836 109 | */ 110 | public function arrayable(): Arrayable 111 | { 112 | return new class implements Arrayable 113 | { 114 | /** 115 | * @return array 116 | */ 117 | public function toArray(): array 118 | { 119 | return [ 120 | 'name' => 'Swoft', 121 | 'notes' => ['New Generation of PHP Framework', 'Hign Performance, Coroutine and Full Stack'], 122 | 'links' => [ 123 | [ 124 | 'name' => 'Home', 125 | 'link' => 'http://www.swoft.org', 126 | ], 127 | [ 128 | 'name' => 'Documentation', 129 | 'link' => 'http://doc.swoft.org', 130 | ], 131 | [ 132 | 'name' => 'Case', 133 | 'link' => 'http://swoft.org/case', 134 | ], 135 | [ 136 | 'name' => 'Issue', 137 | 'link' => 'https://github.com/swoft-cloud/swoft/issues', 138 | ], 139 | [ 140 | 'name' => 'GitHub', 141 | 'link' => 'https://github.com/swoft-cloud/swoft', 142 | ], 143 | ] 144 | ]; 145 | } 146 | 147 | }; 148 | } 149 | 150 | /** 151 | * @RequestMapping() 152 | * @return Response 153 | */ 154 | public function absolutePath(): Response 155 | { 156 | $data = [ 157 | 'name' => 'Swoft', 158 | 'notes' => ['New Generation of PHP Framework', 'Hign Performance, Coroutine and Full Stack'], 159 | 'links' => [ 160 | [ 161 | 'name' => 'Home', 162 | 'link' => 'http://www.swoft.org', 163 | ], 164 | [ 165 | 'name' => 'Documentation', 166 | 'link' => 'http://doc.swoft.org', 167 | ], 168 | [ 169 | 'name' => 'Case', 170 | 'link' => 'http://swoft.org/case', 171 | ], 172 | [ 173 | 'name' => 'Issue', 174 | 'link' => 'https://github.com/swoft-cloud/swoft/issues', 175 | ], 176 | [ 177 | 'name' => 'GitHub', 178 | 'link' => 'https://github.com/swoft-cloud/swoft', 179 | ], 180 | ] 181 | ]; 182 | $template = 'index/index'; 183 | return view($template, $data); 184 | } 185 | 186 | /** 187 | * @RequestMapping() 188 | * @return string 189 | */ 190 | public function raw() 191 | { 192 | $name = 'Swoft'; 193 | return $name; 194 | } 195 | 196 | public function testLog() 197 | { 198 | App::trace('this is app trace'); 199 | Log::trace('this is log trace'); 200 | App::error('this is log error'); 201 | Log::trace('this is log error'); 202 | return ['log']; 203 | } 204 | 205 | /** 206 | * @RequestMapping() 207 | * @throws \Swoft\Http\Server\Exception\BadRequestException 208 | */ 209 | public function exception() 210 | { 211 | throw new BadRequestException('bad request exception'); 212 | } 213 | 214 | /** 215 | * @RequestMapping() 216 | * @param Response $response 217 | * @return Response 218 | */ 219 | public function redirect(Response $response): Response 220 | { 221 | return $response->redirect('/'); 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /src/app/Controllers/MiddlewareController.php: -------------------------------------------------------------------------------- 1 | setName('name'); 29 | $user->setSex(1); 30 | $user->setDesc('this my desc'); 31 | $user->setAge(mt_rand(1, 100)); 32 | 33 | $userId = $user->save()->getResult(); 34 | 35 | return [$userId]; 36 | } 37 | 38 | public function findById() 39 | { 40 | $result = User::findById(41710)->getResult(); 41 | $query = User::findById(41710); 42 | 43 | /* @var User $user */ 44 | $user = $query->getResult(User::class); 45 | 46 | return [$result, $user->getName()]; 47 | } 48 | 49 | public function selectDb(){ 50 | $data = [ 51 | 'name' => 'name', 52 | 'sex' => 1, 53 | 'description' => 'this my desc', 54 | 'age' => mt_rand(1, 100), 55 | ]; 56 | $result = Query::table(User::class)->selectDb('test2')->insert($data)->getResult(); 57 | return $result; 58 | } 59 | 60 | public function selectTable(){ 61 | $data = [ 62 | 'name' => 'name', 63 | 'sex' => 1, 64 | 'description' => 'this my desc', 65 | 'age' => mt_rand(1, 100), 66 | ]; 67 | $result = Query::table('user2')->insert($data)->getResult(); 68 | return $result; 69 | } 70 | 71 | public function transactionCommit() 72 | { 73 | Db::beginTransaction(); 74 | $user = new User(); 75 | $user->setName('name'); 76 | $user->setSex(1); 77 | $user->setDesc('this my desc'); 78 | $user->setAge(mt_rand(1, 100)); 79 | 80 | $userId = $user->save()->getResult(); 81 | Db::commit(); 82 | 83 | 84 | return $userId; 85 | } 86 | 87 | public function transactionRollback() 88 | { 89 | Db::beginTransaction(); 90 | 91 | $user = new User(); 92 | $user->setName('name'); 93 | $user->setSex(1); 94 | $user->setDesc('this my desc'); 95 | $user->setAge(mt_rand(1, 100)); 96 | 97 | $userId = $user->save()->getResult(); 98 | 99 | $count = new Count(); 100 | $count->setUid($userId); 101 | $count->setFollows(mt_rand(1, 100)); 102 | $count->setFans(mt_rand(1, 100)); 103 | 104 | $countId = $count->save()->getResult(); 105 | 106 | Db::rollback(); 107 | 108 | 109 | return [$userId, $countId]; 110 | } 111 | 112 | /** 113 | * This is a wrong operation, only used to test 114 | * 115 | * @return mixed 116 | */ 117 | public function transactionNotCommitOrRollback() 118 | { 119 | Db::beginTransaction(); 120 | $user = new User(); 121 | $user->setName('name'); 122 | $user->setSex(1); 123 | $user->setDesc('this my desc'); 124 | $user->setAge(mt_rand(1, 100)); 125 | 126 | $userId = $user->save()->getResult(); 127 | 128 | // This is a wrong operation, You must to commit or rollback 129 | // ... 130 | 131 | return $userId; 132 | } 133 | 134 | /** 135 | * This is a wrong operation, only used to test 136 | * 137 | * @RequestMapping("tsnonr") 138 | * @return mixed 139 | */ 140 | public function transactionNotCommitOrRollbackAndNotGetResult() 141 | { 142 | Db::beginTransaction(); 143 | $user = new User(); 144 | $user->setName('name'); 145 | $user->setSex(1); 146 | $user->setDesc('this my desc'); 147 | $user->setAge(mt_rand(1, 100)); 148 | 149 | $userId = $user->save(); 150 | 151 | // This is a wrong operation, You must to commit or rollback 152 | // ... 153 | 154 | return ['11']; 155 | } 156 | 157 | /** 158 | * This is a wrong operation, only used to test 159 | * 160 | * @RequestMapping("tsng") 161 | * @return mixed 162 | */ 163 | public function transactionNotGetResult() 164 | { 165 | Db::beginTransaction(); 166 | $user = new User(); 167 | $user->setName('name'); 168 | $user->setSex(1); 169 | $user->setDesc('this my desc'); 170 | $user->setAge(mt_rand(1, 100)); 171 | 172 | $userId = $user->save(); 173 | Db::commit(); 174 | 175 | return [333]; 176 | } 177 | 178 | /** 179 | * This is a wrong operation, only used to test 180 | * 181 | * @RequestMapping("tsng2") 182 | * @return mixed 183 | */ 184 | public function transactionNotGetResult2() 185 | { 186 | Db::beginTransaction(); 187 | $user = new User(); 188 | $user->setName('name'); 189 | $user->setSex(1); 190 | $user->setDesc('this my desc'); 191 | $user->setAge(mt_rand(1, 100)); 192 | 193 | $userId = $user->save(); 194 | Db::rollback(); 195 | 196 | return [33]; 197 | } 198 | 199 | /** 200 | * This is a wrong operation, only used to test 201 | * 202 | * @return mixed 203 | */ 204 | public function notGetResult() 205 | { 206 | $result = User::findById(19362); 207 | $query = User::findById(19362); 208 | 209 | /* @var User $user */ 210 | $user = $query->getResult(User::class); 211 | 212 | return [33]; 213 | } 214 | 215 | /** 216 | * This is a wrong operation, only used to test 217 | * 218 | * @return mixed 219 | */ 220 | public function notGetResult2() 221 | { 222 | $user = new User(); 223 | $user->setName('name'); 224 | $user->setSex(1); 225 | $user->setDesc('this my desc'); 226 | $user->setAge(mt_rand(1, 100)); 227 | 228 | $userId = $user->save()->getResult(); 229 | 230 | $result = User::findById(19362); 231 | $query = User::findById(19362); 232 | 233 | /* @var User $user */ 234 | $user = $query->getResult(User::class); 235 | 236 | return [222]; 237 | } 238 | 239 | /** 240 | * This is a wrong operation, only used to test 241 | * 242 | * @return mixed 243 | */ 244 | public function notGetResult3() 245 | { 246 | $user = new User(); 247 | $user->setName('name'); 248 | $user->setSex(1); 249 | $user->setDesc('this my desc'); 250 | $user->setAge(mt_rand(1, 100)); 251 | 252 | $userId = $user->save(); 253 | 254 | $result = User::findById(19362); 255 | $query = User::findById(19362); 256 | 257 | /* @var User $user */ 258 | $user = $query->getResult(User::class); 259 | 260 | return [33]; 261 | } 262 | } -------------------------------------------------------------------------------- /src/app/Controllers/Psr7Controller.php: -------------------------------------------------------------------------------- 1 | 23 | * @copyright Copyright 2010-2017 Swoft software 24 | * @license PHP Version 7.x {@link http://www.php.net/license/3_0.txt} 25 | */ 26 | class Psr7Controller 27 | { 28 | 29 | /** 30 | * @RequestMapping() 31 | * @param \Swoft\Http\Message\Server\Request $request 32 | * 33 | * @return array 34 | */ 35 | public function get(Request $request) 36 | { 37 | $param1 = $request->query('param1'); 38 | $param2 = $request->query('param2', 'defaultValue'); 39 | return compact('param1', 'param2'); 40 | } 41 | 42 | /** 43 | * @RequestMapping() 44 | * 45 | * @param \Swoft\Http\Message\Server\Request $request 46 | * 47 | * @return array 48 | */ 49 | public function post(Request $request) 50 | { 51 | $param1 = $request->post('param1'); 52 | $param2 = $request->post('param2'); 53 | return compact('param1', 'param2'); 54 | } 55 | 56 | /** 57 | * @RequestMapping() 58 | * 59 | * @param \Swoft\Http\Message\Server\Request $request 60 | * 61 | * @return array 62 | */ 63 | public function input(Request $request) 64 | { 65 | $param1 = $request->input('param1'); 66 | $inputs = $request->input(); 67 | return compact('param1', 'inputs'); 68 | } 69 | 70 | /** 71 | * @RequestMapping() 72 | */ 73 | 74 | /** 75 | * @RequestMapping() 76 | * @param \Swoft\Http\Message\Server\Request $request 77 | * 78 | * @return array 79 | */ 80 | public function raw(Request $request) 81 | { 82 | $param1 = $request->raw(); 83 | return compact('param1'); 84 | } 85 | 86 | /** 87 | * @RequestMapping() 88 | * @param \Swoft\Http\Message\Server\Request $request 89 | * 90 | * @return array 91 | */ 92 | public function cookies(Request $request) 93 | { 94 | $cookie1 = $request->cookie(); 95 | return compact('cookie1'); 96 | } 97 | 98 | /** 99 | * @RequestMapping() 100 | * 101 | * @param \Swoft\Http\Message\Server\Request $request 102 | * 103 | * @return array 104 | */ 105 | public function header(Request $request) 106 | { 107 | $header1 = $request->header(); 108 | $host = $request->header('host'); 109 | return compact('header1', 'host'); 110 | } 111 | 112 | /** 113 | * @RequestMapping() 114 | * @param \Swoft\Http\Message\Server\Request $request 115 | * 116 | * @return array 117 | */ 118 | public function json(Request $request) 119 | { 120 | $json = $request->json(); 121 | $jsonParam = $request->json('jsonParam'); 122 | return compact('json', 'jsonParam'); 123 | } 124 | 125 | /** 126 | * @RequestMapping() 127 | * @param \Swoft\Http\Message\Server\Request $request 128 | * 129 | * @return array 130 | */ 131 | public function files(Request $request) 132 | { 133 | $files = $request->file(); 134 | foreach ($files as $file) { 135 | if ($file instanceof UploadedFileInterface) { 136 | try { 137 | $file->moveTo('@runtime/uploadfiles/1.png'); 138 | $move = true; 139 | } catch (\Throwable $e) { 140 | $move = false; 141 | } 142 | } 143 | } 144 | 145 | return compact('move'); 146 | } 147 | 148 | } -------------------------------------------------------------------------------- /src/app/Controllers/RedisController.php: -------------------------------------------------------------------------------- 1 | demoRedis->set('name', 'swoft'); 46 | $name = $this->demoRedis->get('name'); 47 | 48 | $this->demoRedis->incr('count'); 49 | $this->demoRedis->incrBy('count2', 2); 50 | 51 | return [$result, $name, $this->demoRedis->get('count'), $this->demoRedis->get('count2'), '3']; 52 | } 53 | 54 | public function testCache() 55 | { 56 | $result = $this->cache->set('name', 'swoft'); 57 | $name = $this->cache->get('name'); 58 | 59 | $this->redis->incr('count'); 60 | 61 | $this->redis->incrBy('count2', 2); 62 | 63 | return [$result, $name, $this->redis->get('count'), $this->redis->get('count2'), '3']; 64 | } 65 | 66 | public function testRedis() 67 | { 68 | $result = $this->redis->set('nameRedis', 'swoft2'); 69 | $name = $this->redis->get('nameRedis'); 70 | 71 | return [$result, $name]; 72 | } 73 | 74 | public function error() 75 | { 76 | $result = $this->redis->set('nameRedis', 'swoft2'); 77 | $name = $this->redis->get('nameRedis'); 78 | $ret1 = $this->redis->deferCall('set', ['name1', 'swoft1']); 79 | return [$name]; 80 | } 81 | 82 | public function ab() 83 | { 84 | $result1 = User::query()->where('id', '720')->limit(1)->get()->getResult(); 85 | $result2 = $this->redis->set('test1', 1); 86 | 87 | return [$result1, $result2]; 88 | } 89 | 90 | public function ab2() 91 | { 92 | var_dump($this->redis->incr("count")); 93 | var_dump($this->redis->incr("count")); 94 | var_dump($this->redis->incr("count")); 95 | var_dump($this->redis->incr("count")); 96 | $ret1 = $this->redis->deferCall('set', ['name1', 'swoft1']); 97 | return ['ab']; 98 | } 99 | 100 | public function testFunc() 101 | { 102 | $result = cache()->set('nameFunc', 'swoft3'); 103 | $name = cache()->get('nameFunc'); 104 | 105 | return [$result, $name]; 106 | } 107 | 108 | public function testFunc2() 109 | { 110 | $result = cache()->set('nameFunc2', 'swoft3'); 111 | $name = cache('nameFunc2'); 112 | $name2 = cache('nameFunc3', 'value3'); 113 | 114 | return [$result, $name, $name2]; 115 | } 116 | 117 | public function testDelete() 118 | { 119 | $result = $this->cache->set('name', 'swoft'); 120 | $del = $this->cache->delete('name'); 121 | 122 | return [$result, $del]; 123 | } 124 | 125 | public function clear() 126 | { 127 | $result = $this->cache->clear(); 128 | 129 | return [$result]; 130 | } 131 | 132 | public function setMultiple() 133 | { 134 | $result = $this->cache->setMultiple(['name6' => 'swoft6', 'name8' => 'swoft8']); 135 | $ary = $this->cache->getMultiple(['name6', 'name8']); 136 | 137 | return [$result, $ary]; 138 | } 139 | 140 | public function deleteMultiple() 141 | { 142 | $result = $this->cache->setMultiple(['name6' => 'swoft6', 'name8' => 'swoft8']); 143 | $ary = $this->cache->deleteMultiple(['name6', 'name8']); 144 | 145 | return [$result, $ary]; 146 | } 147 | 148 | public function has() 149 | { 150 | $result = $this->cache->set('name666', 'swoft666'); 151 | $ret = $this->cache->has('name666'); 152 | 153 | return [$result, $ret]; 154 | } 155 | 156 | public function testDefer() 157 | { 158 | $ret1 = $this->redis->deferCall('set', ['name1', 'swoft1']); 159 | // $ret2 = $this->redis->deferCall('set', ['name2', 'swoft2']); 160 | 161 | $r1 = $ret1->getResult(); 162 | $r2 = 1; 163 | // $r2 = $ret2->getResult(); 164 | 165 | $ary = 1; 166 | // $ary = $this->redis->getMultiple(['name1', 'name2']); 167 | 168 | return [$r1, $r2, $ary]; 169 | } 170 | 171 | public function deferError() 172 | { 173 | $ret1 = $this->redis->deferCall('set', ['name1', 'swoft1']); 174 | return 'error'; 175 | } 176 | } -------------------------------------------------------------------------------- /src/app/Controllers/RestController.php: -------------------------------------------------------------------------------- 1 | input('name'); 50 | 51 | $bodyParams = $request->getBodyParams(); 52 | $bodyParams = empty($bodyParams) ? ['create', $name] : $bodyParams; 53 | 54 | return $bodyParams; 55 | } 56 | 57 | /** 58 | * 查询一个用户信息 59 | * 地址:/user/6 60 | * 61 | * @RequestMapping(route="{uid}", method={RequestMethod::GET}) 62 | * 63 | * @param int $uid 64 | * 65 | * @return array 66 | */ 67 | public function getUser(int $uid) 68 | { 69 | return ['getUser', $uid]; 70 | } 71 | 72 | /** 73 | * 查询用户的书籍信息 74 | * 地址:/user/6/book/8 75 | * 76 | * @RequestMapping(route="{userId}/book/{bookId}", method={RequestMethod::GET}) 77 | * 78 | * @param int $userId 79 | * @param string $bookId 80 | * 81 | * @return array 82 | */ 83 | public function getBookFromUser(int $userId, string $bookId) 84 | { 85 | return ['bookFromUser', $userId, $bookId]; 86 | } 87 | 88 | /** 89 | * 删除一个用户信息 90 | * 地址:/user/6 91 | * 92 | * @RequestMapping(route="{uid}", method={RequestMethod::DELETE}) 93 | * 94 | * @param int $uid 95 | * 96 | * @return array 97 | */ 98 | public function deleteUser(int $uid) 99 | { 100 | return ['delete', $uid]; 101 | } 102 | 103 | /** 104 | * 更新一个用户信息 105 | * 地址:/user/6 106 | * 107 | * @RequestMapping(route="{uid}", method={RequestMethod::PUT, RequestMethod::PATCH}) 108 | * 109 | * @param int $uid 110 | * @param Request $request 111 | * @return array 112 | */ 113 | public function updateUser(Request $request, int $uid) 114 | { 115 | $body = $request->getBodyParams(); 116 | $body['update'] = 'update'; 117 | $body['uid'] = $uid; 118 | 119 | return $body; 120 | } 121 | } -------------------------------------------------------------------------------- /src/app/Controllers/RouteController.php: -------------------------------------------------------------------------------- 1 | $router->getStaticRoutes(), 44 | 'regular' => $router->getRegularRoutes(), 45 | 'vague' => $router->getVagueRoutes(), 46 | 'cached' => $router->getCacheRoutes(), 47 | ]; 48 | } 49 | 50 | /** 51 | * @RequestMapping(route="user/{uid}/book/{bid}/{bool}/{name}") 52 | * 53 | * @param bool $bool 54 | * @param Request $request 55 | * @param int $bid 56 | * @param string $name 57 | * @param int $uid 58 | * @param Response $response 59 | * 60 | * @return array 61 | */ 62 | public function funcArgs(bool $bool, Request $request, int $bid, string $name, int $uid, Response $response) 63 | { 64 | return [$bid, $uid, $bool, $name, get_class($request), get_class($response)]; 65 | } 66 | 67 | /** 68 | * @RequestMapping(route="hasNotArg") 69 | * 70 | * @return string 71 | */ 72 | public function hasNotArgs() 73 | { 74 | return 'hasNotArg'; 75 | } 76 | 77 | /** 78 | * @RequestMapping(route="hasAnyArgs/{bid}") 79 | * @param Request $request 80 | * @param int $bid 81 | * 82 | * @return string 83 | */ 84 | public function hasAnyArgs(Request $request, int $bid) 85 | { 86 | return [get_class($request), $bid]; 87 | } 88 | 89 | /** 90 | * @RequestMapping(route="hasMoreArgs") 91 | * 92 | * @param Request $request 93 | * @param int $bid 94 | * 95 | * @return array 96 | */ 97 | public function hasMoreArgs(Request $request, int $bid) 98 | { 99 | return [get_class($request), $bid]; 100 | } 101 | 102 | /** 103 | * optional parameter 104 | * 105 | * @RequestMapping(route="opntion[/{name}]") 106 | * 107 | * @param string $name 108 | * @return array 109 | */ 110 | public function optionalParameter(string $name) 111 | { 112 | return[$name]; 113 | } 114 | 115 | /** 116 | * optional parameter 117 | * 118 | * @RequestMapping(route="anyName/{name}") 119 | * 120 | * @param string $name 121 | * @return array 122 | */ 123 | public function funcAnyName(string $name) 124 | { 125 | return [$name]; 126 | } 127 | 128 | /** 129 | * @param Request $request 130 | * 131 | * @return array 132 | */ 133 | public function notAnnotation(Request $request) 134 | { 135 | return [get_class($request)]; 136 | } 137 | 138 | /** 139 | * @param Request $request 140 | * 141 | * @return array 142 | */ 143 | public function onlyFunc(Request $request) 144 | { 145 | return [get_class($request)]; 146 | } 147 | 148 | /** 149 | * @param Request $request 150 | * 151 | * @return array 152 | */ 153 | public function behind(Request $request) 154 | { 155 | return [get_class($request)]; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/app/Controllers/RpcController.php: -------------------------------------------------------------------------------- 1 | demoService->getUser('11'); 60 | $result2 = $this->demoService->getUsers(['1','2']); 61 | $result3 = $this->demoService->getUserByCond(1, 2, 'boy', 1.6); 62 | 63 | return [ 64 | $result1, 65 | $result2, 66 | $result3, 67 | ]; 68 | } 69 | 70 | /** 71 | * @return array 72 | */ 73 | public function deferFallback() 74 | { 75 | $result1 = $this->demoService->deferGetUser('11')->getResult(); 76 | $result2 = $this->demoService->deferGetUsers(['1','2'])->getResult(); 77 | $result3 = $this->demoService->deferGetUserByCond(1, 2, 'boy', 1.6)->getResult(); 78 | 79 | return [ 80 | 'defer', 81 | $result1, 82 | $result2, 83 | $result3, 84 | ]; 85 | } 86 | 87 | /** 88 | * @RequestMapping(route="call") 89 | * @return array 90 | */ 91 | public function call() 92 | { 93 | $version = $this->demoService->getUser('11'); 94 | $version2 = $this->demoServiceV2->getUser('11'); 95 | 96 | return [ 97 | 'version' => $version, 98 | 'version2' => $version2, 99 | ]; 100 | } 101 | 102 | /** 103 | * Defer call 104 | */ 105 | public function defer(){ 106 | $defer1 = $this->demoService->deferGetUser('123'); 107 | $defer2 = $this->demoServiceV2->deferGetUsers(['2', '3']); 108 | $defer3 = $this->demoServiceV2->deferGetUserByCond(1, 2, 'boy', 1.6); 109 | 110 | $result1 = $defer1->getResult(); 111 | $result2 = $defer2->getResult(); 112 | $result3 = $defer3->getResult(); 113 | 114 | return [$result1, $result2, $result3]; 115 | } 116 | 117 | public function deferError() 118 | { 119 | $defer1 = $this->demoService->deferGetUser('123'); 120 | return ['error']; 121 | } 122 | 123 | public function beanCall() 124 | { 125 | return [ 126 | $this->logic->rpcCall() 127 | ]; 128 | } 129 | 130 | /** 131 | * @RequestMapping("validate") 132 | */ 133 | public function validate() 134 | { 135 | $result = $this->demoService->getUserByCond(1, 2, 'boy', '4'); 136 | 137 | return ['validator', $result]; 138 | } 139 | 140 | 141 | /** 142 | * @RequestMapping("pm") 143 | */ 144 | public function parentMiddleware() 145 | { 146 | $result = $this->mdDemoService->parentMiddleware(); 147 | 148 | return ['parentMiddleware', $result]; 149 | } 150 | 151 | /** 152 | * @RequestMapping("fm") 153 | */ 154 | public function funcMiddleware() 155 | { 156 | $result = $this->mdDemoService->funcMiddleware(); 157 | 158 | return ['funcMiddleware', $result]; 159 | } 160 | } -------------------------------------------------------------------------------- /src/app/Controllers/SessionController.php: -------------------------------------------------------------------------------- 1 | all(); 31 | } 32 | 33 | /** 34 | * @RequestMapping() 35 | * @param \Swoft\Http\Message\Server\Request $request 36 | * @return array 37 | */ 38 | public function set(Request $request): array 39 | { 40 | $key = $request->input('key'); 41 | $value = $request->input('value'); 42 | session()->put([$key => $value]); 43 | return session()->all(); 44 | } 45 | 46 | /** 47 | * @RequestMapping() 48 | * @param \Swoft\Http\Message\Server\Request $request 49 | * @return array 50 | */ 51 | public function remove(Request $request): array 52 | { 53 | $key = $request->input('key'); 54 | session()->remove($key); 55 | return session()->all(); 56 | } 57 | 58 | /** 59 | * @RequestMapping() 60 | */ 61 | public function flush() 62 | { 63 | session()->flush(); 64 | return session()->all(); 65 | } 66 | 67 | /** 68 | * @RequestMapping() 69 | */ 70 | public function regenerateId() 71 | { 72 | return session()->migrate(true); 73 | } 74 | } -------------------------------------------------------------------------------- /src/app/Controllers/TaskController.php: -------------------------------------------------------------------------------- 1 | query('name'); 43 | $postName = $request->post('name'); 44 | 45 | return [$getName, $postName, $name]; 46 | } 47 | 48 | /** 49 | * @RequestMapping("number/{id}") 50 | * 51 | * @Number(from=ValidatorFrom::GET, name="id", min=5, max=10, default=7) 52 | * @Number(from=ValidatorFrom::POST, name="id", min=5, max=10, default=8) 53 | * @Number(from=ValidatorFrom::PATH, name="id", min=5, max=10) 54 | * 55 | * @param Request $request 56 | * @param int $id 57 | * 58 | * @return array 59 | */ 60 | public function number(Request $request, int $id) 61 | { 62 | $get = $request->query('id'); 63 | $post = $request->post('id'); 64 | 65 | return [$get, $post, $id]; 66 | } 67 | 68 | /** 69 | * @RequestMapping("integer/{id}") 70 | * 71 | * @Integer(from=ValidatorFrom::GET, name="id", min=5, max=10, default=7) 72 | * @Integer(from=ValidatorFrom::POST, name="id", min=5, max=10, default=8) 73 | * @Integer(from=ValidatorFrom::PATH, name="id", min=5, max=10) 74 | * 75 | * @param Request $request 76 | * @param int $id 77 | * 78 | * @return array 79 | */ 80 | public function integer(Request $request, int $id) 81 | { 82 | $get = $request->query('id'); 83 | $post = $request->post('id'); 84 | 85 | return [$get, $post, $id]; 86 | } 87 | 88 | /** 89 | * @RequestMapping("float/{id}") 90 | * 91 | * @Floats(from=ValidatorFrom::GET, name="id", min=5.1, max=5.9, default=5.6) 92 | * @Floats(from=ValidatorFrom::POST, name="id", min=5.1, max=5.9, default=5.6) 93 | * @Floats(from=ValidatorFrom::PATH, name="id", min=5.1, max=5.9) 94 | * 95 | * @param Request $request 96 | * @param float $id 97 | * 98 | * @return array 99 | */ 100 | public function float(Request $request, float $id) 101 | { 102 | $get = $request->query('id'); 103 | $post = $request->post('id'); 104 | 105 | return [$get, $post, $id]; 106 | } 107 | 108 | 109 | /** 110 | * @RequestMapping("enum/{name}") 111 | * 112 | * @Enum(from=ValidatorFrom::GET, name="name", values={1,"a",3}, default=1) 113 | * @Enum(from=ValidatorFrom::POST, name="name", values={1,"a",3}, default=1) 114 | * @Enum(from=ValidatorFrom::PATH, name="name", values={1,"a",3}, default=1) 115 | * 116 | * @param string $name 117 | * @param Request $request 118 | * 119 | * @return array 120 | */ 121 | public function estring(Request $request, $name) 122 | { 123 | $getName = $request->query('name'); 124 | $postName = $request->post('name'); 125 | 126 | return [$getName, $postName, $name]; 127 | } 128 | 129 | } -------------------------------------------------------------------------------- /src/app/Exception/SwoftExceptionHandler.php: -------------------------------------------------------------------------------- 1 | 31 | * @copyright Copyright 2010-2016 swoft software 32 | * @license PHP Version 7.x {@link http://www.php.net/license/3_0.txt} 33 | */ 34 | class SwoftExceptionHandler 35 | { 36 | /** 37 | * @Handler(Exception::class) 38 | * 39 | * @param Response $response 40 | * @param \Throwable $throwable 41 | * 42 | * @return Response 43 | */ 44 | public function handlerException(Response $response, \Throwable $throwable) 45 | { 46 | $file = $throwable->getFile(); 47 | $line = $throwable->getLine(); 48 | $code = $throwable->getCode(); 49 | $exception = $throwable->getMessage(); 50 | 51 | $data = ['msg' => $exception, 'file' => $file, 'line' => $line, 'code' => $code]; 52 | App::error(json_encode($data)); 53 | return $response->json($data); 54 | } 55 | 56 | /** 57 | * @Handler(RuntimeException::class) 58 | * 59 | * @param Response $response 60 | * @param \Throwable $throwable 61 | * 62 | * @return Response 63 | */ 64 | public function handlerRuntimeException(Response $response, \Throwable $throwable) 65 | { 66 | $file = $throwable->getFile(); 67 | $code = $throwable->getCode(); 68 | $exception = $throwable->getMessage(); 69 | 70 | return $response->json([$exception, 'runtimeException']); 71 | } 72 | 73 | /** 74 | * @Handler(ValidatorException::class) 75 | * 76 | * @param Response $response 77 | * @param \Throwable $throwable 78 | * 79 | * @return Response 80 | */ 81 | public function handlerValidatorException(Response $response, \Throwable $throwable) 82 | { 83 | $exception = $throwable->getMessage(); 84 | 85 | return $response->json(['message' => $exception]); 86 | } 87 | 88 | /** 89 | * @Handler(BadRequestException::class) 90 | * 91 | * @param Response $response 92 | * @param \Throwable $throwable 93 | * 94 | * @return Response 95 | */ 96 | public function handlerBadRequestException(Response $response, \Throwable $throwable) 97 | { 98 | $exception = $throwable->getMessage(); 99 | 100 | return $response->json(['message' => $exception]); 101 | } 102 | 103 | /** 104 | * @Handler(BadMethodCallException::class) 105 | * 106 | * @param Request $request 107 | * @param Response $response 108 | * @param \Throwable $throwable 109 | * 110 | * @return Response 111 | */ 112 | public function handlerViewException(Request $request, Response $response, \Throwable $throwable) 113 | { 114 | $name = $throwable->getMessage(). $request->getUri()->getPath(); 115 | $notes = [ 116 | 'New Generation of PHP Framework', 117 | 'Hign Performance, Coroutine and Full Stack', 118 | ]; 119 | $links = [ 120 | [ 121 | 'name' => 'Home', 122 | 'link' => 'http://www.swoft.org', 123 | ], 124 | [ 125 | 'name' => 'Documentation', 126 | 'link' => 'http://doc.swoft.org', 127 | ], 128 | [ 129 | 'name' => 'Case', 130 | 'link' => 'http://swoft.org/case', 131 | ], 132 | [ 133 | 'name' => 'Issue', 134 | 'link' => 'https://github.com/swoft-cloud/swoft/issues', 135 | ], 136 | [ 137 | 'name' => 'GitHub', 138 | 'link' => 'https://github.com/swoft-cloud/swoft', 139 | ], 140 | ]; 141 | $data = compact('name', 'notes', 'links'); 142 | 143 | return view('exception/index', $data); 144 | } 145 | 146 | } -------------------------------------------------------------------------------- /src/app/Fallback/DemoServiceFallback.php: -------------------------------------------------------------------------------- 1 | 30 | * [ 31 | * 'uid' => [], 32 | * 'uid2' => [], 33 | * ...... 34 | * ] 35 | *
36 |      */
37 |     public function getUsers(array $ids);
38 | 
39 |     /**
40 |      * @param string $id
41 |      *
42 |      * @return array
43 |      */
44 |     public function getUser(string $id);
45 | 
46 |     public function getUserByCond(int $type, int $uid, string $name, float $price, string $desc = 'desc');
47 | }


--------------------------------------------------------------------------------
/src/app/Lib/MdDemoInterface.php:
--------------------------------------------------------------------------------
 1 | keepAlive();
33 | 
34 |     }
35 | }


--------------------------------------------------------------------------------
/src/app/Listener/TaskFinish.php:
--------------------------------------------------------------------------------
 1 | getParams());
31 |     }
32 | }


--------------------------------------------------------------------------------
/src/app/Middlewares/ActionTestMiddleware.php:
--------------------------------------------------------------------------------
 1 | 
25 |  * @copyright Copyright 2010-2017 Swoft software
26 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
27 |  */
28 | class ActionTestMiddleware implements MiddlewareInterface
29 | {
30 | 
31 |     /**
32 |      * Process an incoming server request and return a response, optionally delegating
33 |      * response creation to a handler.
34 |      *
35 |      * @param \Psr\Http\Message\ServerRequestInterface $request
36 |      * @param \Psr\Http\Server\RequestHandlerInterface $handler
37 |      * @return \Psr\Http\Message\ResponseInterface
38 |      * @throws \InvalidArgumentException
39 |      */
40 |     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
41 |     {
42 |         $response = $handler->handle($request);
43 |         return $response->withAddedHeader('Middleware-Action-Test', 'success');
44 |     }
45 | }


--------------------------------------------------------------------------------
/src/app/Middlewares/ControllerSubMiddleware.php:
--------------------------------------------------------------------------------
 1 | 
26 |  * @copyright Copyright 2010-2016 swoft software
27 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
28 |  */
29 | class ControllerSubMiddleware implements MiddlewareInterface
30 | {
31 |     /**
32 |      * @param \Psr\Http\Message\ServerRequestInterface $request
33 |      * @param \Psr\Http\Server\RequestHandlerInterface $handler
34 |      * @return \Psr\Http\Message\ResponseInterface
35 |      * @throws \InvalidArgumentException
36 |      */
37 |     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
38 |     {
39 |         $response = $handler->handle($request);
40 |         return $response->withAddedHeader('Controller-Sub-Middleware', 'success');
41 |     }
42 | }


--------------------------------------------------------------------------------
/src/app/Middlewares/ControllerTestMiddleware.php:
--------------------------------------------------------------------------------
 1 | handle($request);
34 |         return $response->withAddedHeader('Controller-Test-Middleware', 'success');
35 |     }
36 | }


--------------------------------------------------------------------------------
/src/app/Middlewares/GroupTestMiddleware.php:
--------------------------------------------------------------------------------
 1 | 
25 |  * @copyright Copyright 2010-2017 Swoft software
26 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
27 |  */
28 | class GroupTestMiddleware implements MiddlewareInterface
29 | {
30 | 
31 |     /**
32 |      * Process an incoming server request and return a response, optionally delegating
33 |      * response creation to a handler.
34 |      *
35 |      * @param \Psr\Http\Message\ServerRequestInterface $request
36 |      * @param \Psr\Http\Server\RequestHandlerInterface $handler
37 |      * @return \Psr\Http\Message\ResponseInterface
38 |      * @throws \InvalidArgumentException
39 |      */
40 |     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
41 |     {
42 |         $response = $handler->handle($request);
43 |         return $response->withAddedHeader('Middleware-Group-Test', 'success');
44 |     }
45 | }


--------------------------------------------------------------------------------
/src/app/Middlewares/ServiceMiddleware.php:
--------------------------------------------------------------------------------
 1 | 
26 |  * @copyright Copyright 2010-2016 swoft software
27 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
28 |  */
29 | class ServiceMiddleware implements MiddlewareInterface
30 | {
31 |     /**
32 |      * @param \Psr\Http\Message\ServerRequestInterface     $request
33 |      * @param \Psr\Http\Server\RequestHandlerInterface $handler
34 |      *
35 |      * @return \Psr\Http\Message\ResponseInterface
36 |      */
37 |     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
38 |     {
39 |         var_dump('ServiceMiddleware->before');
40 |         $response = $handler->handle($request);
41 |         var_dump('ServiceMiddleware->after');
42 |         return $response;
43 |     }
44 | }


--------------------------------------------------------------------------------
/src/app/Middlewares/ServiceSubMiddleware.php:
--------------------------------------------------------------------------------
 1 | 
26 |  * @copyright Copyright 2010-2016 swoft software
27 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
28 |  */
29 | class ServiceSubMiddleware implements MiddlewareInterface
30 | {
31 |     /**
32 |      * @param \Psr\Http\Message\ServerRequestInterface     $request
33 |      * @param \Psr\Http\Server\RequestHandlerInterface $handler
34 |      *
35 |      * @return \Psr\Http\Message\ResponseInterface
36 |      */
37 |     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
38 |     {
39 |         var_dump('ServiceSubMiddleware->before');
40 |         return $handler->handle($request);
41 |     }
42 | }


--------------------------------------------------------------------------------
/src/app/Middlewares/SubMiddleware.php:
--------------------------------------------------------------------------------
 1 | 
25 |  * @copyright Copyright 2010-2017 Swoft software
26 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
27 |  */
28 | class SubMiddleware implements MiddlewareInterface
29 | {
30 | 
31 |     /**
32 |      * Process an incoming server request and return a response, optionally delegating
33 |      * response creation to a handler.
34 |      *
35 |      * @param \Psr\Http\Message\ServerRequestInterface $request
36 |      * @param \Psr\Http\Server\RequestHandlerInterface $handler
37 |      * @return \Psr\Http\Message\ResponseInterface
38 |      * @throws \InvalidArgumentException
39 |      */
40 |     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
41 |     {
42 |         $response = $handler->handle($request);
43 |         $response = $response->withAddedHeader('Sub-Middleware-Test', 'success');
44 |         return $response;
45 |     }
46 | }


--------------------------------------------------------------------------------
/src/app/Middlewares/SubMiddlewares.php:
--------------------------------------------------------------------------------
 1 | 
26 |  * @copyright Copyright 2010-2017 Swoft software
27 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
28 |  */
29 | class SubMiddlewares implements MiddlewareInterface
30 | {
31 | 
32 |     /**
33 |      * Process an incoming server request and return a response, optionally delegating
34 |      * response creation to a handler.
35 |      *
36 |      * @param \Psr\Http\Message\ServerRequestInterface $request
37 |      * @param \Psr\Http\Server\RequestHandlerInterface $handler
38 |      * @return \Psr\Http\Message\ResponseInterface
39 |      */
40 |     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
41 |     {
42 |         if ($handler instanceof RequestHandler) {
43 |             $handler->insertMiddlewares([
44 |                 SubMiddleware::class,
45 |             ]);
46 |         }
47 |         return $handler->handle($request);
48 |     }
49 | }


--------------------------------------------------------------------------------
/src/app/Models/Dao/UserDao.php:
--------------------------------------------------------------------------------
 1 | 
21 |  * @copyright Copyright 2010-2016 Swoft software
22 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
23 |  */
24 | class UserDao
25 | {
26 |     public function getUserInfo()
27 |     {
28 |         return [
29 |             'uid' => 666,
30 |             'name' => 'stelin'
31 |         ];
32 |     }
33 | }
34 | 


--------------------------------------------------------------------------------
/src/app/Models/Dao/UserExtDao.php:
--------------------------------------------------------------------------------
 1 | 
21 |  * @copyright Copyright 2010-2016 Swoft software
22 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
23 |  */
24 | class UserExtDao
25 | {
26 |     public function getExtInfo()
27 |     {
28 |         return [
29 |             'age' => 18,
30 |             'desc' => 'hello',
31 |             'address' => 'chengdu'
32 |         ];
33 |     }
34 | }
35 | 


--------------------------------------------------------------------------------
/src/app/Models/Data/UserData.php:
--------------------------------------------------------------------------------
 1 | 
23 |  * @copyright Copyright 2010-2016 Swoft software
24 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
25 |  */
26 | class UserData
27 | {
28 |     /**
29 |      *
30 |      * @Inject()
31 |      * @var UserDao
32 |      */
33 |     private $userDao;
34 | 
35 |     public function getUserInfo()
36 |     {
37 |         return $this->userDao->getUserInfo();
38 |     }
39 | }
40 | 


--------------------------------------------------------------------------------
/src/app/Models/Data/UserExtData.php:
--------------------------------------------------------------------------------
 1 | 
23 |  * @copyright Copyright 2010-2016 Swoft software
24 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
25 |  */
26 | class UserExtData
27 | {
28 |     /**
29 |      * @Inject()
30 |      * @var UserExtDao
31 |      */
32 |     private $userExtDao;
33 | 
34 |     /**
35 |      * @Inject()
36 |      * @var UserData
37 |      */
38 |     private $userData;
39 | 
40 |     public function getExtInfo()
41 |     {
42 |         return $this->userExtDao->getExtInfo();
43 |     }
44 | }
45 | 


--------------------------------------------------------------------------------
/src/app/Models/Entity/Count.php:
--------------------------------------------------------------------------------
  1 | 
 28 |  * @copyright Copyright 2010-2016 swoft software
 29 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
 30 |  */
 31 | class Count extends Model
 32 | {
 33 |     /**
 34 |      * 用户ID
 35 |      *
 36 |      * @Column(name="uid", type=Types::INT)
 37 |      * @Id()
 38 |      * @var null|int
 39 |      */
 40 |     private $uid;
 41 | 
 42 |     /**
 43 |      * 粉丝数
 44 |      *
 45 |      * @Column(name="fans", type=Types::NUMBER)
 46 |      * @var int
 47 |      */
 48 |     private $fans = 0;
 49 | 
 50 |     /**
 51 |      * 关注数
 52 |      *
 53 |      * @Column("follows", type=Types::NUMBER)
 54 |      * @var int
 55 |      */
 56 |     private $follows = 0;
 57 | 
 58 |     /**
 59 |      * @return int|null
 60 |      */
 61 |     public function getUid()
 62 |     {
 63 |         return $this->uid;
 64 |     }
 65 | 
 66 |     /**
 67 |      * @param int|null $uid
 68 |      */
 69 |     public function setUid($uid)
 70 |     {
 71 |         $this->uid = $uid;
 72 |     }
 73 | 
 74 |     /**
 75 |      * @return int
 76 |      */
 77 |     public function getFans(): int
 78 |     {
 79 |         return $this->fans;
 80 |     }
 81 | 
 82 |     /**
 83 |      * @param int $fans
 84 |      */
 85 |     public function setFans(int $fans)
 86 |     {
 87 |         $this->fans = $fans;
 88 |     }
 89 | 
 90 |     /**
 91 |      * @return mixed
 92 |      */
 93 |     public function getFollows()
 94 |     {
 95 |         return $this->follows;
 96 |     }
 97 | 
 98 |     /**
 99 |      * @param mixed $follows
100 |      */
101 |     public function setFollows($follows)
102 |     {
103 |         $this->follows = $follows;
104 |     }
105 | }


--------------------------------------------------------------------------------
/src/app/Models/Entity/User.php:
--------------------------------------------------------------------------------
  1 | 
 29 |  * @copyright Copyright 2010-2016 Swoft software
 30 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
 31 |  */
 32 | class User extends Model
 33 | {
 34 |     /**
 35 |      * 主键ID
 36 |      *
 37 |      * @Id()
 38 |      * @Column(name="id", type=Types::INT)
 39 |      * @var null|int
 40 |      */
 41 |     private $id;
 42 | 
 43 |     /**
 44 |      * 名称
 45 |      *
 46 |      * @Column(name="name", type=Types::STRING, length=20)
 47 |      * @Required()
 48 |      * @var null|string
 49 |      */
 50 |     private $name;
 51 | 
 52 |     /**
 53 |      * 年龄
 54 |      *
 55 |      * @Column(name="age", type=Types::INT)
 56 |      * @var int
 57 |      */
 58 |     private $age = 0;
 59 | 
 60 |     /**
 61 |      * 性别
 62 |      *
 63 |      * @Column(name="sex", type="int")
 64 |      * @var int
 65 |      */
 66 |     private $sex = 0;
 67 | 
 68 |     /**
 69 |      * 描述
 70 |      *
 71 |      * @Column(name="description", type="string")
 72 |      * @var string
 73 |      */
 74 |     private $desc = '';
 75 | 
 76 |     /**
 77 |      * 非数据库字段,未定义映射关系
 78 |      *
 79 |      * @var mixed
 80 |      */
 81 |     private $otherProperty;
 82 | 
 83 |     /**
 84 |      * @return int|null
 85 |      */
 86 |     public function getId()
 87 |     {
 88 |         return $this->id;
 89 |     }
 90 | 
 91 |     /**
 92 |      * @param int|null $id
 93 |      */
 94 |     public function setId($id)
 95 |     {
 96 |         $this->id = $id;
 97 |     }
 98 | 
 99 |     /**
100 |      * @return null|string
101 |      */
102 |     public function getName()
103 |     {
104 |         return $this->name;
105 |     }
106 | 
107 |     /**
108 |      * @param null|string $name
109 |      */
110 |     public function setName($name)
111 |     {
112 |         $this->name = $name;
113 |     }
114 | 
115 |     /**
116 |      * @return int
117 |      */
118 |     public function getAge(): int
119 |     {
120 |         return $this->age;
121 |     }
122 | 
123 |     /**
124 |      * @param int $age
125 |      */
126 |     public function setAge(int $age)
127 |     {
128 |         $this->age = $age;
129 |     }
130 | 
131 |     /**
132 |      * @return int
133 |      */
134 |     public function getSex(): int
135 |     {
136 |         return $this->sex;
137 |     }
138 | 
139 |     /**
140 |      * @param int $sex
141 |      */
142 |     public function setSex(int $sex)
143 |     {
144 |         $this->sex = $sex;
145 |     }
146 | 
147 |     /**
148 |      * @return string
149 |      */
150 |     public function getDesc(): string
151 |     {
152 |         return $this->desc;
153 |     }
154 | 
155 |     /**
156 |      * @param string $desc
157 |      */
158 |     public function setDesc(string $desc)
159 |     {
160 |         $this->desc = $desc;
161 |     }
162 | 
163 |     /**
164 |      * @return mixed
165 |      */
166 |     public function getOtherProperty()
167 |     {
168 |         return $this->otherProperty;
169 |     }
170 | 
171 |     /**
172 |      * @param mixed $otherProperty
173 |      */
174 |     public function setOtherProperty($otherProperty)
175 |     {
176 |         $this->otherProperty = $otherProperty;
177 |     }
178 | }
179 | 


--------------------------------------------------------------------------------
/src/app/Models/Logic/IndexLogic.php:
--------------------------------------------------------------------------------
 1 | 
24 |  * @copyright Copyright 2010-2016 Swoft software
25 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
26 |  */
27 | class IndexLogic
28 | {
29 |     /**
30 |      *
31 |      * @Inject()
32 |      * @var UserData
33 |      */
34 |     private $userData;
35 | 
36 |     /**
37 |      *
38 |      * @Inject()
39 |      * @var UserExtData
40 |      */
41 |     private $userExtData;
42 | 
43 |     public function getUser()
44 |     {
45 |         $base = $this->userData->getUserInfo();
46 |         $ext = $this->userExtData->getExtInfo();
47 | 
48 |         return array_merge($base, $ext);
49 |     }
50 | }
51 | 


--------------------------------------------------------------------------------
/src/app/Models/Logic/UserLogic.php:
--------------------------------------------------------------------------------
 1 | 
24 |  * @copyright Copyright 2010-2016 swoft software
25 |  * @license   PHP Version 7.x {@link http://www.php.net/license/3_0.txt}
26 |  */
27 | class UserLogic
28 | {
29 |     /**
30 |      * @Reference("user")
31 |      *
32 |      * @var \App\Lib\DemoInterface
33 |      */
34 |     private $demoService;
35 | 
36 |     /**
37 |      * @Reference(name="user", version="1.0.1")
38 |      *
39 |      * @var \App\Lib\DemoInterface
40 |      */
41 |     private $demoServiceV2;
42 | 
43 |     public function rpcCall()
44 |     {
45 |         return ['bean', $this->demoService->getUser('12'), $this->demoServiceV2->getUser('16')];
46 |     }
47 | 
48 |     public function getUserInfo(array $uids)
49 |     {
50 |         $user = [
51 |             'name' => 'boby',
52 |             'desc' => 'this is boby'
53 |         ];
54 | 
55 |         $data = [];
56 |         foreach ($uids as $uid) {
57 |             $user['uid'] = $uid;
58 |             $data[] = $user;
59 |         }
60 | 
61 |         return $data;
62 |     }
63 | }


--------------------------------------------------------------------------------
/src/app/Pool/Config/DemoRedisPoolConfig.php:
--------------------------------------------------------------------------------
 1 | 
 84 |      * [
 85 |      *  '127.0.0.1:88',
 86 |      *  '127.0.0.1:88'
 87 |      * ]
 88 |      * 
89 | * 90 | * @Value(name="${config.service.user.uri}", env="${USER_POOL_URI}") 91 | * @var array 92 | */ 93 | protected $uri = []; 94 | 95 | /** 96 | * whether to user provider(consul/etcd/zookeeper) 97 | * 98 | * @Value(name="${config.service.user.useProvider}", env="${USER_POOL_USE_PROVIDER}") 99 | * @var bool 100 | */ 101 | protected $useProvider = false; 102 | 103 | /** 104 | * the default balancer is random balancer 105 | * 106 | * @Value(name="${config.service.user.balancer}", env="${USER_POOL_BALANCER}") 107 | * @var string 108 | */ 109 | protected $balancer = ''; 110 | 111 | /** 112 | * the default provider is consul provider 113 | * 114 | * @Value(name="${config.service.user.provider}", env="${USER_POOL_PROVIDER}") 115 | * @var string 116 | */ 117 | protected $provider = ''; 118 | } 119 | -------------------------------------------------------------------------------- /src/app/Pool/DemoRedisPool.php: -------------------------------------------------------------------------------- 1 | getPname(); 29 | $processName = "$pname myProcess process"; 30 | $process->name($processName); 31 | 32 | echo "Custom child process \n"; 33 | var_dump(Coroutine::id()); 34 | } 35 | 36 | public function check(): bool 37 | { 38 | return true; 39 | } 40 | } -------------------------------------------------------------------------------- /src/app/Services/DemoService.php: -------------------------------------------------------------------------------- 1 | getTarsConf(); 19 | if( !empty($conf) ){ 20 | $node = $conf['tars']['application']['server']['node']; 21 | $nodeInfo = Utils::parseNodeInfo($node); 22 | return $nodeInfo; 23 | }else{ 24 | return []; 25 | } 26 | } 27 | 28 | public function getTarsConf(){ 29 | $tars_conf = dirname(BASE_PATH,2).'/conf/'.env('PNAME').'.config.conf'; 30 | 31 | if( is_file($tars_conf) ){ 32 | $conf = Utils::parseFile($tars_conf); 33 | return $conf; 34 | }else{ 35 | var_dump('get tars_conf file error : '.$tars_conf); 36 | return []; 37 | } 38 | } 39 | 40 | public function keepAlive() 41 | { 42 | $pname = env('PNAME'); 43 | $pname = explode('.',$pname); 44 | 45 | $adapter = env('PNAME').'.objAdapter'; 46 | $application = $pname[0]; 47 | $serverName = $pname[1]; 48 | $masterPid = getmypid(); 49 | 50 | $nodeInfo = $this->getNodeInfo(); 51 | if( empty($nodeInfo) ){ 52 | var_dump('keepAlive getNodeInfo fail'); 53 | return null; 54 | } 55 | $host = $nodeInfo['host']; 56 | $port = $nodeInfo['port']; 57 | $objName = $nodeInfo['objName']; 58 | 59 | $serverInfo = new ServerInfo(); 60 | $serverInfo->adapter = $adapter; 61 | $serverInfo->application = $application; 62 | $serverInfo->serverName = $serverName; 63 | $serverInfo->pid = $masterPid; 64 | 65 | $serverF = new ServerFSync($host, $port, $objName); 66 | $serverF->keepAlive($serverInfo); 67 | 68 | $adminServerInfo = new ServerInfo(); 69 | $adminServerInfo->adapter = 'AdminAdapter'; 70 | $adminServerInfo->application = $application; 71 | $adminServerInfo->serverName = $serverName; 72 | $adminServerInfo->pid = $masterPid; 73 | $serverF->keepAlive($adminServerInfo); 74 | 75 | var_dump(' keepalive '); 76 | } 77 | } -------------------------------------------------------------------------------- /src/app/Tasks/SyncTask.php: -------------------------------------------------------------------------------- 1 | deferCall('set', ['name1', 'swoft1'])->getResult(); 91 | // $ret1 = $cache->deferCall('set', ['name1', 'swoft1']); 92 | //// return cache('cacheKey'); 93 | // return 111; 94 | // } 95 | // 96 | // /** 97 | // * Mysql task 98 | // * 99 | // * @return array 100 | // */ 101 | // public function mysql(){ 102 | // $result = User::findById(4212)->getResult(); 103 | // 104 | // $query = User::findById(4212); 105 | // 106 | // /* @var User $user */ 107 | // $user = $query->getResult(User::class); 108 | // return [$result, $user->getName()]; 109 | // } 110 | // 111 | // /** 112 | // * Http task 113 | // * 114 | // * @return mixed 115 | // */ 116 | // public function http() 117 | // { 118 | // $client = new Client(); 119 | // $response = $client->get('http://www.swoft.org')->getResponse()->getBody()->getContents(); 120 | // $response2 = $client->get('http://127.0.0.1/redis/testCache')->getResponse()->getBody()->getContents(); 121 | // 122 | // $data['result1'] = $response; 123 | // $data['result2'] = $response2; 124 | // return $data; 125 | // } 126 | // 127 | // public function console(string $data) 128 | // { 129 | // var_dump('console', $data); 130 | // return ['console']; 131 | // } 132 | // 133 | // /** 134 | // * Rpc task 135 | // * 136 | // * @return mixed 137 | // */ 138 | // public function rpc() 139 | // { 140 | // $user = $this->demoService->getUser('6666'); 141 | // $defer1 = $this->demoService->deferGetUser('666'); 142 | // $defer2 = $this->demoService->deferGetUser('888'); 143 | // 144 | // $result1 = $defer1->getResult(); 145 | // $result2 = $defer2->getResult(); 146 | // return [$user, $result1, $result2]; 147 | // } 148 | // 149 | // /** 150 | // * Rpc task 151 | // * 152 | // * @return mixed 153 | // */ 154 | // public function rpc2() 155 | // { 156 | // return $this->logic->rpcCall(); 157 | // } 158 | // 159 | // /** 160 | // * crontab定时任务 161 | // * 每一秒执行一次 162 | // * 163 | // * @Scheduled(cron="* * * * * *") 164 | // */ 165 | // public function cronTask() 166 | // { 167 | // echo time() . "每一秒执行一次 \n"; 168 | // return 'cron'; 169 | // } 170 | // 171 | // /** 172 | // * 每分钟第3-5秒执行 173 | // * 174 | // * @Scheduled(cron="3-5 * * * * *") 175 | // */ 176 | // public function cronooTask() 177 | // { 178 | // echo time() . "第3-5秒执行\n"; 179 | // return 'cron'; 180 | // } 181 | // 182 | //} 183 | -------------------------------------------------------------------------------- /src/app/Tasks/TarsKeepAliveTask.php: -------------------------------------------------------------------------------- 1 | keepAlive(); 32 | return 'cron'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/app/WebSocket/EchoController.php: -------------------------------------------------------------------------------- 1 | push($fd, 'hello, welcome! :)'); 35 | } 36 | 37 | /** 38 | * @param Server $server 39 | * @param Frame $frame 40 | */ 41 | public function onMessage(Server $server, Frame $frame) 42 | { 43 | $server->push($frame->fd, 'hello, I have received your message: ' . $frame->data); 44 | } 45 | 46 | /** 47 | * @param Server $server 48 | * @param int $fd 49 | */ 50 | public function onClose(Server $server, int $fd) 51 | { 52 | // do something. eg. record log, unbind user ... 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/bin/bootstrap.php: -------------------------------------------------------------------------------- 1 | bootstrap(); 20 | -------------------------------------------------------------------------------- /src/bin/swoft: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); -------------------------------------------------------------------------------- /src/changelog.md: -------------------------------------------------------------------------------- 1 | # Change log 2 | 3 | # 2018-04-05 4 | 5 | * 添加 websocket 支持 6 | * 完成基本的 devtool 7 | 8 | # 2018-03-05 9 | * 组件化拆分 10 | 11 | # 2018-01-05 12 | 13 | * 重构HttpClient 14 | * 重构Redis 15 | * 创建实体新增特殊变量别名 16 | 17 | # 2017-12-26 18 | 19 | * 重构连接池 20 | 21 | # 2017-12-20 22 | 23 | * 新增匹配事件 24 | 25 | # 2017-12-16 26 | 27 | * 重构热更新兼容跨平台 28 | 29 | # 2017-12-11 30 | 31 | * 事件管理改动,使用 psr 14 实现 32 | 33 | # 2017-12-10 34 | 35 | * 新增HTTP、RPC验证器 36 | * 新增HTTP、RPC中间件 37 | 38 | # 2017-12-2 39 | 40 | * 新增RESTful风格兼容 41 | 42 | # 2017-11-29 43 | 44 | * 重构请求流程 45 | * 简化控制器和RPC服务操作 46 | * 增加 创建实体 操作 47 | 48 | # 2017-11-15 49 | 50 | * 增加 Pipeline 组件 51 | 52 | # 2017-11-13 53 | 54 | * 增加 PHPUnit 单元测试 55 | 56 | # 2017-11-12 57 | 58 | * 根据 Psr-7 重构 Request/Response 59 | 60 | # 2017-11-02 61 | 62 | * 重构 config 配置 63 | * 新增 .env 配置环境信息 64 | 65 | # 2017-11-01 66 | 67 | * 新增定时任务 68 | 69 | # 2017-10-24 70 | 71 | * 协程、异步任务投递 72 | * 自定义用户进程 73 | * RPC, Redis, Http, Mysql 协程和同步客户端无缝切换 74 | * HTTP 和 RPC 服务器分开管理 75 | 76 | # 2017-09-19 77 | 78 | * 数据库 ORM 79 | 80 | # 2017-09-02 81 | 82 | * 别名机制 83 | * 事件机制 84 | * 国际化(i18n) 85 | * 命名空间统一大写。 86 | 87 | # 2017-08-28 88 | * 新增 Inotify 自动 Reload 89 | 90 | # 2017-08-24 91 | 92 | * 重写 IoC 容器 93 | * 新增控制器路由注解注册 94 | * 重写容器注入,不再依赖 PHP-DI 95 | 96 | # 2017-08-15 97 | 98 | * 重构 Console 命令行 99 | 100 | # ...... 101 | -------------------------------------------------------------------------------- /src/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "swoft/swoft", 3 | "type": "project", 4 | "keywords": [ 5 | "php", 6 | "swoole", 7 | "swoft" 8 | ], 9 | "description": "Modern High performance AOP and Coroutine PHP Framework, base on Swoole 2", 10 | "license": "Apache-2.0", 11 | "require": { 12 | "php": ">=7.0", 13 | "swoft/framework": "^1.0", 14 | "swoft/rpc": "^1.0", 15 | "swoft/rpc-server": "^1.0", 16 | "swoft/rpc-client": "^1.0", 17 | "swoft/http-server": "^1.0", 18 | "swoft/http-client": "^1.0", 19 | "swoft/websocket-server": "^1.0", 20 | "swoft/task": "^1.0", 21 | "swoft/http-message": "^1.0", 22 | "swoft/view": "^1.0", 23 | "swoft/db": "^1.0", 24 | "swoft/cache": "^1.0", 25 | "swoft/redis": "^1.0", 26 | "swoft/console": "^1.0", 27 | "swoft/devtool": "^1.0", 28 | "swoft/session": "^1.0", 29 | "swoft/i18n": "^1.0", 30 | "swoft/process": "^1.0", 31 | "swoft/memory": "^1.0", 32 | "swoft/service-governance": "^1.0", 33 | "phptars/tars-registry": "~0.1.0", 34 | "phptars/tars-deploy": "~0.1.0", 35 | "phptars/tars-utils": "~0.1.0", 36 | "phptars/tars-report": "~0.1.0", 37 | "phptars/tars-client": "~0.1.0", 38 | "phptars/tars2php": "~0.1.0" 39 | }, 40 | "require-dev": { 41 | "eaglewu/swoole-ide-helper": "dev-master", 42 | "phpunit/phpunit": "^5.7" 43 | }, 44 | "autoload": { 45 | "psr-4": { 46 | "App\\": "app/" 47 | }, 48 | "files": [ 49 | "app/Swoft.php" 50 | ] 51 | }, 52 | "autoload-dev": { 53 | "psr-4": { 54 | "Swoft\\Test\\": "test/" 55 | } 56 | }, 57 | "scripts": { 58 | "post-root-package-install": [ 59 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 60 | ], 61 | "test": "./vendor/bin/phpunit -c phpunit.xml", 62 | "deploy": "\\Tars\\deploy\\Deploy::run" 63 | }, 64 | "repositories": [ 65 | ] 66 | } 67 | -------------------------------------------------------------------------------- /src/config/beans/base.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'serverDispatcher' => [ 12 | 'middlewares' => [ 13 | \Swoft\View\Middleware\ViewMiddleware::class, 14 | // \Swoft\Devtool\Middleware\DevToolMiddleware::class, 15 | // \Swoft\Session\Middleware\SessionMiddleware::class, 16 | ] 17 | ], 18 | 'httpRouter' => [ 19 | 'ignoreLastSlash' => false, 20 | 'tmpCacheNumber' => 1000, 21 | 'matchAll' => '', 22 | ], 23 | 'requestParser' => [ 24 | 'parsers' => [ 25 | 26 | ], 27 | ], 28 | 'view' => [ 29 | 'viewsPath' => '@resources/views/', 30 | ], 31 | 'cache' => [ 32 | 'driver' => 'redis', 33 | ], 34 | 'demoRedis' => [ 35 | 'class' => \Swoft\Redis\Redis::class, 36 | 'poolName' => 'demoRedis' 37 | ] 38 | ]; 39 | -------------------------------------------------------------------------------- /src/config/beans/console.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 12 | ]; -------------------------------------------------------------------------------- /src/config/beans/log.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'noticeHandler' => [ 12 | 'class' => \Swoft\Log\FileHandler::class, 13 | 'logFile' => '@runtime/logs/notice.log', 14 | 'formatter' => '${lineFormatter}', 15 | 'levels' => [ 16 | \Swoft\Log\Logger::NOTICE, 17 | \Swoft\Log\Logger::INFO, 18 | \Swoft\Log\Logger::DEBUG, 19 | \Swoft\Log\Logger::TRACE, 20 | ], 21 | ], 22 | 'applicationHandler' => [ 23 | 'class' => \Swoft\Log\FileHandler::class, 24 | 'logFile' => '@runtime/logs/error.log', 25 | 'formatter' => '${lineFormatter}', 26 | 'levels' => [ 27 | \Swoft\Log\Logger::ERROR, 28 | \Swoft\Log\Logger::WARNING, 29 | ], 30 | ], 31 | 'logger' => [ 32 | 'name' => APP_NAME, 33 | 'enable' => false, 34 | 'flushInterval' => 100, 35 | 'flushRequest' => true, 36 | 'handlers' => [ 37 | '${noticeHandler}', 38 | '${applicationHandler}', 39 | ], 40 | ], 41 | ]; 42 | -------------------------------------------------------------------------------- /src/config/beans/service.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | ]; -------------------------------------------------------------------------------- /src/config/define.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | ! defined('DS') && define('DS', DIRECTORY_SEPARATOR); 11 | // App name 12 | ! defined('APP_NAME') && define('APP_NAME', 'swoft'); 13 | // Project base path 14 | ! defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 1)); 15 | 16 | // Register alias 17 | $aliases = [ 18 | '@root' => BASE_PATH, 19 | '@env' => '@root', 20 | '@app' => '@root/app', 21 | '@res' => '@root/resources', 22 | '@runtime' => '@root/runtime', 23 | '@configs' => '@root/config', 24 | '@resources' => '@root/resources', 25 | '@beans' => '@configs/beans', 26 | '@properties' => '@configs/properties', 27 | '@console' => '@beans/console.php', 28 | '@commands' => '@app/command', 29 | '@vendor' => '@root/vendor', 30 | ]; 31 | 32 | \Swoft\App::setAliases($aliases); 33 | -------------------------------------------------------------------------------- /src/config/properties/app.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'version' => '1.0', 12 | 'autoInitBean' => true, 13 | 'bootScan' => [ 14 | 'App\Commands', 15 | 'App\Boot', 16 | ], 17 | 'beanScan' => [ 18 | 'App\Controllers', 19 | 'App\Models', 20 | 'App\Middlewares', 21 | 'App\Tasks', 22 | 'App\Services', 23 | 'App\Breaker', 24 | 'App\Pool', 25 | 'App\Exception', 26 | 'App\Listener', 27 | 'App\Process', 28 | 'App\Fallback', 29 | 'App\WebSocket', 30 | 'App\Tasks', 31 | ], 32 | 'I18n' => [ 33 | 'sourceLanguage' => '@root/resources/messages/', 34 | ], 35 | 'env' => 'Base', 36 | 'db' => require __DIR__ . DS . 'db.php', 37 | 'cache' => require __DIR__ . DS . 'cache.php', 38 | 'service' => require __DIR__ . DS . 'service.php', 39 | 'breaker' => require __DIR__ . DS . 'breaker.php', 40 | 'provider' => require __DIR__ . DS . 'provider.php', 41 | ]; 42 | -------------------------------------------------------------------------------- /src/config/properties/breaker.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'user' => [ 12 | 'failCount' => 3, 13 | 'successCount' => 3, 14 | 'delayTime' => 500, 15 | ], 16 | ]; -------------------------------------------------------------------------------- /src/config/properties/cache.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'redis' => [ 12 | 'name' => 'redis', 13 | 'uri' => [ 14 | '127.0.0.1:6379', 15 | '127.0.0.1:6379', 16 | ], 17 | 'minActive' => 8, 18 | 'maxActive' => 8, 19 | 'maxWait' => 8, 20 | 'maxWaitTime' => 3, 21 | 'maxIdleTime' => 60, 22 | 'timeout' => 8, 23 | 'db' => 1, 24 | 'prefix' => 'redis_', 25 | 'serialize' => 0, 26 | ], 27 | 'demoRedis' => [ 28 | 'db' => 2, 29 | 'prefix' => 'demo_redis_', 30 | ], 31 | ]; -------------------------------------------------------------------------------- /src/config/properties/db.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'master' => [ 12 | 'name' => 'master', 13 | 'uri' => [ 14 | '127.0.0.1:3306/test?user=root&password=123456&charset=utf8', 15 | '127.0.0.1:3306/test?user=root&password=123456&charset=utf8', 16 | ], 17 | 'minActive' => 8, 18 | 'maxActive' => 8, 19 | 'maxWait' => 8, 20 | 'timeout' => 8, 21 | 'maxIdleTime' => 60, 22 | 'maxWaitTime' => 3, 23 | ], 24 | 25 | 'slave' => [ 26 | 'name' => 'slave', 27 | 'uri' => [ 28 | '127.0.0.1:3306/test?user=root&password=123456&charset=utf8', 29 | '127.0.0.1:3306/test?user=root&password=123456&charset=utf8', 30 | ], 31 | 'minActive' => 8, 32 | 'maxActive' => 8, 33 | 'maxWait' => 8, 34 | 'timeout' => 8, 35 | 'maxIdleTime' => 60, 36 | 'maxWaitTime' => 3, 37 | ], 38 | ]; -------------------------------------------------------------------------------- /src/config/properties/provider.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'consul' => [ 12 | 'address' => '', 13 | 'port' => 8500, 14 | 'register' => [ 15 | 'id' => '', 16 | 'name' => '', 17 | 'tags' => [], 18 | 'enableTagOverride' => false, 19 | 'service' => [ 20 | 'address' => 'localhost', 21 | 'port' => '8099', 22 | ], 23 | 'check' => [ 24 | 'id' => '', 25 | 'name' => '', 26 | 'tcp' => 'localhost:8099', 27 | 'interval' => 10, 28 | 'timeout' => 1, 29 | ], 30 | ], 31 | 'discovery' => [ 32 | 'name' => 'user', 33 | 'dc' => 'dc', 34 | 'near' => '', 35 | 'tag' =>'', 36 | 'passing' => true 37 | ] 38 | ], 39 | ]; -------------------------------------------------------------------------------- /src/config/properties/service.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'user' => [ 12 | 'name' => 'redis', 13 | 'uri' => [ 14 | '127.0.0.1:8099', 15 | '127.0.0.1:8099', 16 | ], 17 | 'minActive' => 8, 18 | 'maxActive' => 8, 19 | 'maxWait' => 8, 20 | 'maxWaitTime' => 3, 21 | 'maxIdleTime' => 60, 22 | 'timeout' => 8, 23 | 'useProvider' => false, 24 | 'balancer' => 'random', 25 | 'provider' => 'consul', 26 | ] 27 | ]; -------------------------------------------------------------------------------- /src/config/server.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'server' => [ 12 | 'pfile' => env('PFILE', '/tmp/swoft.pid'), 13 | 'pname' => env('PNAME', 'php-swoft'), 14 | 'tcpable' => env('TCPABLE', true), 15 | 'cronable' => env('CRONABLE', false), 16 | 'autoReload' => env('AUTO_RELOAD', true), 17 | ], 18 | 'tcp' => [ 19 | 'host' => env('TCP_HOST', '0.0.0.0'), 20 | 'port' => env('TCP_PORT', 8099), 21 | 'mode' => env('TCP_MODE', SWOOLE_PROCESS), 22 | 'type' => env('TCP_TYPE', SWOOLE_SOCK_TCP), 23 | 'package_max_length' => env('TCP_PACKAGE_MAX_LENGTH', 2048), 24 | 'open_eof_check' => env('TCP_OPEN_EOF_CHECK', false), 25 | ], 26 | 'http' => [ 27 | 'host' => env('HTTP_HOST', '0.0.0.0'), 28 | 'port' => env('HTTP_PORT', 80), 29 | 'mode' => env('HTTP_MODE', SWOOLE_PROCESS), 30 | 'type' => env('HTTP_TYPE', SWOOLE_SOCK_TCP), 31 | ], 32 | 'ws' => [ 33 | // enable handle http request ? 34 | 'enable_http' => env('WS_ENABLE_HTTP', true), 35 | // other settings will extend the 'http' config 36 | // you can define separately to overwrite existing settings 37 | ], 38 | 'crontab' => [ 39 | 'task_count' => env('CRONTAB_TASK_COUNT', 1024), 40 | 'task_queue' => env('CRONTAB_TASK_QUEUE', 2048), 41 | ], 42 | 'setting' => [ 43 | 'worker_num' => env('WORKER_NUM', 1), 44 | 'max_request' => env('MAX_REQUEST', 10000), 45 | 'daemonize' => env('DAEMONIZE', 0), 46 | 'dispatch_mode' => env('DISPATCH_MODE', 2), 47 | 'log_file' => env('LOG_FILE', '@runtime/logs/swoole.log'), 48 | 'task_worker_num' => env('TASK_WORKER_NUM', 1), 49 | 'package_max_length' => env('PACKAGE_MAX_LENGTH', 2048), 50 | 'upload_tmp_dir' => env('UPLOAD_TMP_DIR', '@runtime/uploadfiles'), 51 | 'document_root' => env('DOCUMENT_ROOT', BASE_PATH . '/public'), 52 | 'enable_static_handler' => env('ENABLE_STATIC_HANDLER', true), 53 | 'open_http2_protocol' => env('OPEN_HTTP2_PROTOCOL', false), 54 | 'ssl_cert_file' => env('SSL_CERT_FILE', ''), 55 | 'ssl_key_file' => env('SSL_KEY_FILE', ''), 56 | 'task_ipc_mode' => env('TASK_IPC_MODE', 2), 57 | 'message_queue_key' => env('MESSAGE_QUEUE_KEY', 0x70001001), 58 | 'task_tmpdir' => env('TASK_TMPDIR', '/tmp'), 59 | ], 60 | ]; 61 | -------------------------------------------------------------------------------- /src/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | swoft: 4 | container_name: swoft 5 | image: swoft/swoft:latest 6 | ports: 7 | - "80:80" 8 | volumes: 9 | - ./:/var/www/swoft 10 | stdin_open: true 11 | tty: true 12 | command: php /var/www/swoft/bin/swoft start 13 | -------------------------------------------------------------------------------- /src/index.php: -------------------------------------------------------------------------------- 1 | stripComments(true) 14 | ->setShebang(true) 15 | ->addSuffix('.json')// for add composer.json 16 | ->addExclude([ 17 | 'test', 18 | 'tests', 19 | 'runtime', 20 | 'eaglewu', 21 | ]) 22 | ->addFile([ 23 | 'LICENSE', 24 | 'README.md', 25 | ]) 26 | ->setCliIndex('bin/swoft') 27 | // ->setWebIndex('web/index.php') 28 | // ->setVersionFile('config/config.php') 29 | ; 30 | 31 | // Command Controller 命令类不去除注释,注释上是命令帮助信息 32 | $compiler->setStripFilter(function ($file) { 33 | /** @var \SplFileInfo $file */ 34 | $path = $file->getPath(); 35 | 36 | if (strpos($path, 'swoft')) { 37 | return false; 38 | } 39 | 40 | return false === strpos($file->getFilename(), 'Command.php'); 41 | }); 42 | -------------------------------------------------------------------------------- /src/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./test 14 | 15 | 16 | 17 | 18 | ./app 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpp2009/swoftInTars/825198c61de555184cd908aca1871590cb967837/src/public/.gitkeep -------------------------------------------------------------------------------- /src/resources/README.md: -------------------------------------------------------------------------------- 1 | # 资源目录 2 | 3 | - views - 视图资源 4 | - messages - 翻译资源 -------------------------------------------------------------------------------- /src/resources/languages/en/default.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'title' => 'en title' 12 | ]; 13 | -------------------------------------------------------------------------------- /src/resources/languages/en/msg.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'body' => 'this is msg [%s] %d', 12 | ]; 13 | -------------------------------------------------------------------------------- /src/resources/languages/zh/default.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'title' => '中文标题' 12 | ]; 13 | -------------------------------------------------------------------------------- /src/resources/languages/zh/msg.php: -------------------------------------------------------------------------------- 1 | 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | return [ 11 | 'body' => '这是一条消息 [%s] %d', 12 | ]; 13 | -------------------------------------------------------------------------------- /src/resources/views/demo/content.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Swoft framework

5 |

6 | swoft 是基于swoole协程2.x的高性能PHP微服务框架,内置http,rpc 服务器。框架全协程实现,性能优于传统的php-fpm模式。 7 |

8 |
9 |

更多信息请访问 github 或者 官方文档.

10 |

11 | Github 12 | Document 13 |

14 |
15 |
16 |

使用布局文件

17 |
18 | view file: 
19 | 
20 | layout file: 
21 | 
22 | view method: 
23 | 
24 | 
25 | 使用布局文件, 方式有两种:
26 | 
27 | 1. 在配置中 配置默认的布局文件,那这里即使不设置 layout, 也会使用默认的
28 | 2. 如这里一样,手动设置一个布局文件。它的优先级更高(即使有默认的布局文件,也会使用当前传入的替代。)
29 |     
30 |
31 |
32 |
-------------------------------------------------------------------------------- /src/resources/views/demo/view.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | Document 9 | 10 | 11 | 12 |
13 | 33 |
34 |
35 |
36 |
37 |
38 |
39 |

Fluid jumbotron

40 |

This is a modified jumbotron that occupies the entire horizontal space of its parent.

41 |
42 |
43 |

没有使用 layout

44 |
45 | view file: 
46 | 
47 | view method: 
48 |       
49 |
50 |
51 |
52 | 53 | -------------------------------------------------------------------------------- /src/resources/views/exception/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <?= $name ?> 9 | 10 | 11 | 12 | 13 | 14 | 73 | 74 | 75 |
76 | 77 |
78 |
79 | 80 |
81 | 82 | 83 |
84 | 85 |
86 | 87 | 88 | 93 |
94 |
95 | 96 | -------------------------------------------------------------------------------- /src/resources/views/index/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <?= $name ?> 9 | 10 | 11 | 12 | 13 | 14 | 73 | 74 | 75 |
76 | 77 |
78 |
79 | 80 |
81 | 82 | 83 |
84 | 85 |
86 | 87 | 88 | 93 |
94 |
95 | 96 | -------------------------------------------------------------------------------- /src/resources/views/layouts/default.php: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | Demo for layout 14 | 15 | 16 | 17 | include('layouts/default/header') ?> 18 | 19 |
20 | 21 |
{_CONTENT_}
22 | include('layouts/default/footer') ?> 23 |
24 | 25 | -------------------------------------------------------------------------------- /src/resources/views/layouts/default/footer.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/resources/views/layouts/default/header.php: -------------------------------------------------------------------------------- 1 |
2 | 29 |
-------------------------------------------------------------------------------- /src/runtime/logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpp2009/swoftInTars/825198c61de555184cd908aca1871590cb967837/src/runtime/logs/.gitkeep -------------------------------------------------------------------------------- /src/runtime/uploadfiles/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dpp2009/swoftInTars/825198c61de555184cd908aca1871590cb967837/src/runtime/uploadfiles/.gitkeep -------------------------------------------------------------------------------- /src/test/Cases/AbstractTestCase.php: -------------------------------------------------------------------------------- 1 | buildMockRequest($method, $uri, $parameters, $accept, $swooleRequest, $headers); 56 | 57 | $swooleRequest->setRawContent($rawContent); 58 | 59 | $request = Request::loadFromSwooleRequest($swooleRequest); 60 | $response = new Response($swooleResponse); 61 | 62 | /** @var \Swoft\Http\Server\ServerDispatcher $dispatcher */ 63 | $dispatcher = App::getBean('serverDispatcher'); 64 | return $dispatcher->dispatch($request, $response); 65 | } 66 | 67 | /** 68 | * Send a mock json request 69 | * 70 | * @param string $method 71 | * @param string $uri 72 | * @param array $parameters 73 | * @param array $headers 74 | * @param string $rawContent 75 | * @return bool|\Swoft\Http\Message\Testing\Web\Response 76 | */ 77 | public function json( 78 | string $method, 79 | string $uri, 80 | array $parameters = [], 81 | array $headers = [], 82 | string $rawContent = '' 83 | ) { 84 | return $this->request($method, $uri, $parameters, self::ACCEPT_JSON, $headers, $rawContent); 85 | } 86 | 87 | /** 88 | * Send a mock view request 89 | * 90 | * @param string $method 91 | * @param string $uri 92 | * @param array $parameters 93 | * @param array $headers 94 | * @param string $rawContent 95 | * @return bool|\Swoft\Http\Message\Testing\Web\Response 96 | */ 97 | public function view( 98 | string $method, 99 | string $uri, 100 | array $parameters = [], 101 | array $headers = [], 102 | string $rawContent = '' 103 | ) { 104 | return $this->request($method, $uri, $parameters, self::ACCEPT_VIEW, $headers, $rawContent); 105 | } 106 | 107 | /** 108 | * Send a mock raw content request 109 | * 110 | * @param string $method 111 | * @param string $uri 112 | * @param array $parameters 113 | * @param array $headers 114 | * @param string $rawContent 115 | * @return bool|\Swoft\Http\Message\Testing\Web\Response 116 | */ 117 | public function raw( 118 | string $method, 119 | string $uri, 120 | array $parameters = [], 121 | array $headers = [], 122 | string $rawContent = '' 123 | ) { 124 | return $this->request($method, $uri, $parameters, self::ACCEPT_RAW, $headers, $rawContent); 125 | } 126 | 127 | /** 128 | * @param string $method 129 | * @param string $uri 130 | * @param array $parameters 131 | * @param string $accept 132 | * @param \Swoole\Http\Request $swooleRequest 133 | * @param array $headers 134 | */ 135 | protected function buildMockRequest( 136 | string $method, 137 | string $uri, 138 | array $parameters, 139 | string $accept, 140 | &$swooleRequest, 141 | array $headers = [] 142 | ) { 143 | $urlAry = parse_url($uri); 144 | $urlParams = []; 145 | if (isset($urlAry['query'])) { 146 | parse_str($urlAry['query'], $urlParams); 147 | } 148 | $defaultHeaders = [ 149 | 'host' => '127.0.0.1', 150 | 'connection' => 'keep-alive', 151 | 'cache-control' => 'max-age=0', 152 | 'user-agent' => 'PHPUnit', 153 | 'upgrade-insecure-requests' => '1', 154 | 'accept' => $accept, 155 | 'dnt' => '1', 156 | 'accept-encoding' => 'gzip, deflate, br', 157 | 'accept-language' => 'zh-CN,zh;q=0.8,en;q=0.6,it-IT;q=0.4,it;q=0.2', 158 | ]; 159 | 160 | $swooleRequest->fd = 1; 161 | $swooleRequest->header = ArrayHelper::merge($headers, $defaultHeaders); 162 | $swooleRequest->server = [ 163 | 'request_method' => $method, 164 | 'request_uri' => $uri, 165 | 'path_info' => '/', 166 | 'request_time' => microtime(), 167 | 'request_time_float' => microtime(true), 168 | 'server_port' => 80, 169 | 'remote_port' => 54235, 170 | 'remote_addr' => '10.0.2.2', 171 | 'master_time' => microtime(), 172 | 'server_protocol' => 'HTTP/1.1', 173 | 'server_software' => 'swoole-http-server', 174 | ]; 175 | 176 | if ($method == 'GET') { 177 | $swooleRequest->get = $parameters; 178 | } elseif ($method == 'POST') { 179 | $swooleRequest->post = $parameters; 180 | } 181 | 182 | if (! empty($urlParams)) { 183 | $get = empty($swooleRequest->get) ? [] : $swooleRequest->get; 184 | $swooleRequest->get = array_merge($urlParams, $get); 185 | } 186 | } 187 | } -------------------------------------------------------------------------------- /src/test/Cases/DemoControllerTest.php: -------------------------------------------------------------------------------- 1 | 18 | * @copyright Copyright 2010-2017 Swoft software 19 | * @license PHP Version 7.x {@link http://www.php.net/license/3_0.txt} 20 | */ 21 | class DemoControllerTest extends AbstractTestCase 22 | { 23 | 24 | /** 25 | * @test 26 | * @covers \App\Controllers\DemoController 27 | */ 28 | public function actionView() 29 | { 30 | $response = $this->request('GET', '/demo2/view', [], parent::ACCEPT_VIEW); 31 | $response->assertSuccessful()->assertSee('Swoft')->assertSee('没有使用 layout'); 32 | } 33 | 34 | /** 35 | * @test 36 | * @covers \App\Controllers\DemoController 37 | */ 38 | public function actionLayout() 39 | { 40 | $response = $this->request('GET', '/demo2/layout', [], parent::ACCEPT_VIEW); 41 | $response->assertSuccessful()->assertSee('Swoft')->assertSee('使用布局文件'); 42 | } 43 | 44 | /** 45 | * @test 46 | */ 47 | public function actionI18n() 48 | { 49 | $response = $this->request('GET', '/demo2/i18n', [], parent::ACCEPT_VIEW); 50 | $response->assertSuccessful()->assertSee('title'); 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /src/test/Cases/IndexControllerTest.php: -------------------------------------------------------------------------------- 1 | 19 | * @copyright Copyright 2010-2017 Swoft software 20 | * @license PHP Version 7.x {@link http://www.php.net/license/3_0.txt} 21 | */ 22 | class IndexControllerTest extends AbstractTestCase 23 | { 24 | 25 | /** 26 | * @test 27 | * @covers \App\Controllers\IndexController 28 | */ 29 | public function testIndex() 30 | { 31 | $expectedResult = [ 32 | 'name' => 'Swoft', 33 | 'notes' => [ 34 | 'New Generation of PHP Framework', 35 | 'Hign Performance, Coroutine and Full Stack' 36 | ], 37 | 'links' => [ 38 | [ 39 | 'name' => 'Home', 40 | 'link' => 'http://www.swoft.org', 41 | ], 42 | [ 43 | 'name' => 'Documentation', 44 | 'link' => 'http://doc.swoft.org', 45 | ], 46 | [ 47 | 'name' => 'Case', 48 | 'link' => 'http://swoft.org/case', 49 | ], 50 | [ 51 | 'name' => 'Issue', 52 | 'link' => 'https://github.com/swoft-cloud/swoft/issues', 53 | ], 54 | [ 55 | 'name' => 'GitHub', 56 | 'link' => 'https://github.com/swoft-cloud/swoft', 57 | ], 58 | ] 59 | ]; 60 | 61 | $jsonAssert = function ($response) use ($expectedResult) { 62 | $this->assertInstanceOf(Response::class, $response); 63 | /** @var Response $response */ 64 | $response->assertSuccessful() 65 | ->assertHeaderContain('Content-Type', 'application/json') 66 | ->assertSee('Swoft') 67 | ->assertSeeText('New Generation of PHP Framework') 68 | ->assertDontSee('Swoole') 69 | ->assertDontSeeText('Swoole') 70 | ->assertJson(['name' => 'Swoft']) 71 | ->assertExactJson($expectedResult) 72 | ->assertJsonFragment(['name' => 'Home']) 73 | ->assertJsonMissing(['name' => 'Swoole']) 74 | ->assertJsonStructure(['name', 'notes']); 75 | }; 76 | // Json model 77 | $response = $this->request('GET', '/', [], parent::ACCEPT_JSON); 78 | $response->assertHeaderContain('Content-Type', parent::ACCEPT_JSON); 79 | $jsonAssert($response); 80 | 81 | // Raw model 82 | $response = $this->request('GET', '/', [], parent::ACCEPT_RAW); 83 | $response->assertHeaderContain('Content-Type', parent::ACCEPT_JSON); 84 | $jsonAssert($response); 85 | 86 | // View model 87 | $response = $this->request('GET', '/', [], parent::ACCEPT_VIEW); 88 | $response->assertSuccessful() 89 | ->assertSee($expectedResult['name']) 90 | ->assertSee($expectedResult['notes'][0]) 91 | ->assertSee($expectedResult['notes'][1]) 92 | ->assertHeaderContain('Content-Type', 'text/html'); 93 | 94 | // absolutePath 95 | $response = $this->request('GET', '/index/absolutePath', [], parent::ACCEPT_VIEW); 96 | $response->assertSuccessful() 97 | ->assertSee($expectedResult['name']) 98 | ->assertSee($expectedResult['notes'][0]) 99 | ->assertSee($expectedResult['notes'][1]) 100 | ->assertHeader('Content-Type', 'text/html'); 101 | } 102 | 103 | /** 104 | * @test 105 | * @covers \App\Controllers\IndexController 106 | */ 107 | public function testException() 108 | { 109 | $data = [ 110 | 'message' => 'bad request exception' 111 | ]; 112 | 113 | $response = $this->request('GET', '/index/exception', [], parent::ACCEPT_JSON); 114 | $response->assertJson($data); 115 | } 116 | 117 | /** 118 | * @test 119 | * @covers \App\Controllers\IndexController 120 | */ 121 | public function testRaw() 122 | { 123 | $expected = 'Swoft'; 124 | $response = $this->request('GET', '/index/raw', [], parent::ACCEPT_RAW); 125 | $response->assertSuccessful()->assertSee($expected); 126 | 127 | $response = $this->request('GET', '/index/raw', [], parent::ACCEPT_JSON); 128 | $response->assertSuccessful()->assertJson(['data' => $expected]); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/test/Cases/MiddlewareTest.php: -------------------------------------------------------------------------------- 1 | request('GET', '/middleware/action1', [], parent::ACCEPT_JSON); 25 | $response->assertExactJson(['middleware']); 26 | $response->assertHeader('Middleware-Group-Test', 'success'); 27 | $response->assertHeader('Sub-Middleware-Test', 'success'); 28 | $response->assertHeader('Middleware-Action-Test', 'success'); 29 | } 30 | 31 | /** 32 | * @covers \App\Controllers\MiddlewareController::action2 33 | * @test 34 | */ 35 | public function action2() 36 | { 37 | $response = $this->request('GET', '/middleware/action2', [], parent::ACCEPT_JSON); 38 | $response->assertExactJson(['middleware2']); 39 | $response->assertHeader('Middleware-Group-Test', 'success'); 40 | $response->assertHeader('Sub-Middleware-Test', 'success'); 41 | $response->assertHeader('Middleware-Action-Test', 'success'); 42 | } 43 | 44 | /** 45 | * @covers \App\Controllers\MiddlewareController::action3 46 | * @test 47 | */ 48 | public function action3() 49 | { 50 | $response = $this->request('GET', '/middleware/action3', [], parent::ACCEPT_JSON); 51 | $response->assertExactJson(['middleware3']); 52 | $response->assertHeader('Controller-Test-Middleware', 'success'); 53 | $response->assertHeader('Controller-Sub-Middleware', 'success'); 54 | } 55 | } -------------------------------------------------------------------------------- /src/test/Cases/RedisControllerTest.php: -------------------------------------------------------------------------------- 1 | has('test'); 31 | $this->isRedisConnected = true; 32 | } catch (\Exception $e) { 33 | // No connection or else error 34 | } 35 | } 36 | 37 | /** 38 | * @param \Closure $closure 39 | */ 40 | protected function runRedisTest(\Closure $closure) 41 | { 42 | if ($this->isRedisConnected) { 43 | $closure(); 44 | } else { 45 | $this->markTestSkipped('No redis connection'); 46 | } 47 | } 48 | 49 | /** 50 | * @test 51 | * @requires extension redis 52 | */ 53 | public function cache() 54 | { 55 | $this->runRedisTest(function () { 56 | $expected = [ 57 | true, 58 | 'swoft', 59 | ]; 60 | $response = $this->request('GET', '/redis/testCache', [], parent::ACCEPT_JSON); 61 | $response->assertSuccessful()->assertJson($expected); 62 | }); 63 | } 64 | 65 | /** 66 | * @test 67 | * @requires extension redis 68 | */ 69 | public function redis() 70 | { 71 | $this->runRedisTest(function () { 72 | $expected = [ 73 | true, 74 | 'swoft2', 75 | ]; 76 | $response = $this->request('GET', '/redis/testRedis', [], parent::ACCEPT_JSON); 77 | $response->assertSuccessful()->assertJson($expected); 78 | }); 79 | } 80 | 81 | /** 82 | * @test 83 | * @requires extension redis 84 | */ 85 | public function func() 86 | { 87 | $this->runRedisTest(function () { 88 | $expected = [ 89 | true, 90 | 'swoft3', 91 | ]; 92 | $response = $this->request('GET', '/redis/testFunc', [], parent::ACCEPT_JSON); 93 | $response->assertSuccessful()->assertJson($expected); 94 | }); 95 | } 96 | 97 | /** 98 | * @test 99 | * @requires extension redis 100 | */ 101 | public function func2() 102 | { 103 | $this->runRedisTest(function () { 104 | $expected = [ 105 | true, 106 | 'swoft3', 107 | 'value3', 108 | ]; 109 | $response = $this->request('GET', '/redis/testFunc2', [], parent::ACCEPT_JSON); 110 | $response->assertSuccessful()->assertJson($expected); 111 | }); 112 | } 113 | 114 | /** 115 | * @test 116 | * @requires extension redis 117 | */ 118 | public function delete() 119 | { 120 | $this->runRedisTest(function () { 121 | $expected = [ 122 | true, 123 | 1, 124 | ]; 125 | $response = $this->request('GET', '/redis/testDelete', [], parent::ACCEPT_JSON); 126 | $response->assertSuccessful()->assertJson($expected); 127 | }); 128 | } 129 | 130 | /** 131 | * @test 132 | * @requires extension redis 133 | */ 134 | public function clear() 135 | { 136 | $this->runRedisTest(function () { 137 | $expected = [ 138 | true, 139 | ]; 140 | $response = $this->request('GET', '/redis/clear', [], parent::ACCEPT_JSON); 141 | $response->assertSuccessful()->assertJson($expected); 142 | }); 143 | } 144 | 145 | /** 146 | * @test 147 | * @requires extension redis 148 | */ 149 | public function multiple() 150 | { 151 | $this->runRedisTest(function () { 152 | $expected = [ 153 | true, 154 | [ 155 | 'name6' => 'swoft6', 156 | 'name8' => 'swoft8', 157 | ], 158 | ]; 159 | $response = $this->request('GET', '/redis/setMultiple', [], parent::ACCEPT_JSON); 160 | $response->assertSuccessful()->assertJson($expected); 161 | }); 162 | } 163 | 164 | /** 165 | * @test 166 | * @requires extension redis 167 | */ 168 | public function deleteMultiple() 169 | { 170 | $this->runRedisTest(function () { 171 | $expected = [ 172 | true, 173 | 2, 174 | ]; 175 | $response = $this->request('GET', '/redis/deleteMultiple', [], parent::ACCEPT_JSON); 176 | $response->assertSuccessful()->assertJson($expected); 177 | }); 178 | } 179 | 180 | /** 181 | * @test 182 | * @requires extension redis 183 | */ 184 | public function has() 185 | { 186 | $this->runRedisTest(function () { 187 | $expected = [ 188 | true, 189 | true, 190 | ]; 191 | $response = $this->request('GET', '/redis/has', [], parent::ACCEPT_JSON); 192 | $response->assertSuccessful()->assertJson($expected); 193 | }); 194 | } 195 | } -------------------------------------------------------------------------------- /src/test/Cases/RestTest.php: -------------------------------------------------------------------------------- 1 | 19 | * @copyright Copyright 2010-2016 swoft software 20 | * @license PHP Version 7.x {@link http://www.php.net/license/3_0.txt} 21 | */ 22 | class RestTest extends AbstractTestCase 23 | { 24 | /** 25 | * @covers \App\Controllers\RestController@list 26 | */ 27 | public function testList() 28 | { 29 | $data = ['list']; 30 | $response = $this->request('GET', '/user', [], parent::ACCEPT_JSON); 31 | $response->assertExactJson($data); 32 | } 33 | 34 | /** 35 | * @covers \App\Controllers\RestController@create 36 | */ 37 | public function testCreate() 38 | { 39 | $data = ['create', 'stelin']; 40 | $response = $this->request('POST', '/user', ['name' => 'stelin'], parent::ACCEPT_JSON); 41 | $response->assertExactJson($data); 42 | 43 | $headers = [ 44 | 'Content-Type' => 'application/json' 45 | ]; 46 | $content = '{"name":"stelin","age":18,"desc":"swoft framework"}'; 47 | $data = [ 48 | 'name' => 'stelin', 49 | 'age' => 18, 50 | 'desc' => 'swoft framework', 51 | ]; 52 | $response = $this->request('PUT', '/user', [], parent::ACCEPT_JSON, $headers, $content); 53 | $response->assertExactJson($data); 54 | } 55 | 56 | /** 57 | * @covers \App\Controllers\RestController@getUser 58 | */ 59 | public function testGetUser() 60 | { 61 | $data = ['getUser',123]; 62 | $response = $this->request('GET', '/user/123', [], parent::ACCEPT_JSON); 63 | $response->assertExactJson($data); 64 | } 65 | 66 | /** 67 | * @covers \App\Controllers\RestController@getBookFromUser 68 | */ 69 | public function testGetBookFromUser() 70 | { 71 | $data = ['bookFromUser',123, '456']; 72 | $response = $this->request('GET', '/user/123/book/456', [], parent::ACCEPT_JSON); 73 | $response->assertExactJson($data); 74 | } 75 | 76 | /** 77 | * @covers \App\Controllers\RestController@deleteUser 78 | */ 79 | public function testDeleteUser() 80 | { 81 | $data = ['delete',123]; 82 | $response = $this->request('DELETE', '/user/123', [], parent::ACCEPT_JSON); 83 | $response->assertExactJson($data); 84 | } 85 | 86 | /** 87 | * @covers \App\Controllers\RestController@updateUser 88 | */ 89 | public function testUpdateUser() 90 | { 91 | $headers = [ 92 | 'Content-Type' => 'application/json' 93 | ]; 94 | $content = '{"name":"stelin","age":18,"desc":"swoft framework"}'; 95 | $data = [ 96 | 'name' => 'stelin', 97 | 'age' => 18, 98 | 'desc' => 'swoft framework', 99 | 'update' => 'update', 100 | 'uid' => 123 101 | ]; 102 | 103 | $response = $this->request('PUT', '/user/123', [], parent::ACCEPT_JSON, $headers, $content); 104 | $response->assertExactJson($data); 105 | 106 | $response = $this->request('PATCH', '/user/123', [], parent::ACCEPT_JSON, $headers, $content); 107 | $response->assertExactJson($data); 108 | } 109 | } -------------------------------------------------------------------------------- /src/test/Cases/RouteTest.php: -------------------------------------------------------------------------------- 1 | 19 | * @copyright Copyright 2010-2016 swoft software 20 | * @license PHP Version 7.x {@link http://www.php.net/license/3_0.txt} 21 | */ 22 | use Swoft\Http\Message\Testing\Web\Request; 23 | use Swoft\Http\Message\Testing\Web\Response; 24 | 25 | class RouteTest extends AbstractTestCase 26 | { 27 | /** 28 | * @covers \App\Controllers\RouteController@funcArgs 29 | */ 30 | public function testFuncArgs() 31 | { 32 | $data = [ 33 | 456, 34 | 123, 35 | true, 36 | 'test', 37 | Request::class, 38 | Response::class, 39 | ]; 40 | $response = $this->request('GET', '/route/user/123/book/456/1/test', [], parent::ACCEPT_JSON); 41 | $response->assertExactJson($data); 42 | } 43 | 44 | /** 45 | * @covers \App\Controllers\RouteController::hasNotArgs 46 | */ 47 | public function testHasNotArg() 48 | { 49 | $response = $this->request('GET', '/route/hasNotArg', [], parent::ACCEPT_JSON); 50 | $response->assertExactJson(['data' => 'hasNotArg']); 51 | } 52 | 53 | /** 54 | * @covers \App\Controllers\RouteController@hasAnyArgs 55 | */ 56 | public function testHasAnyArgs() 57 | { 58 | $response = $this->request('GET', '/route/hasAnyArgs/123', [], parent::ACCEPT_JSON); 59 | $response->assertExactJson([Request::class, 123]); 60 | } 61 | 62 | /** 63 | * @covers \App\Controllers\RouteController@optionalParameter 64 | */ 65 | public function testOptionnalParameter() 66 | { 67 | $response = $this->request('GET', '/route/opntion/arg1', [], parent::ACCEPT_JSON); 68 | $response->assertExactJson(['arg1']); 69 | 70 | $response = $this->request('GET', '/route/opntion', [], parent::ACCEPT_JSON); 71 | $response->assertExactJson(['']); 72 | } 73 | 74 | /** 75 | * @covers \App\Controllers\RouteController@hasMoreArgs 76 | */ 77 | public function testHasMoreArgs() 78 | { 79 | $response = $this->request('GET', '/route/hasMoreArgs', [], parent::ACCEPT_JSON); 80 | $response->assertExactJson([Request::class, 0]); 81 | } 82 | 83 | /** 84 | * @covers \App\Controllers\RouteController@notAnnotation 85 | */ 86 | public function testNotAnnotation() 87 | { 88 | $response = $this->request('GET', '/route/notAnnotation', [], parent::ACCEPT_JSON); 89 | $response->assertExactJson([Request::class]); 90 | } 91 | 92 | /** 93 | * @covers \App\Controllers\RouteController@onlyFunc 94 | */ 95 | public function testOnlyFunc() 96 | { 97 | $response = $this->request('GET', '/route/onlyFunc', [], parent::ACCEPT_JSON); 98 | $response->assertExactJson([Request::class]); 99 | } 100 | 101 | /** 102 | * @covers \App\Controllers\RouteController@behind 103 | */ 104 | public function testBehindAction() 105 | { 106 | $response = $this->request('GET', '/route/behind', [], parent::ACCEPT_JSON); 107 | $response->assertExactJson([Request::class]); 108 | } 109 | 110 | /** 111 | * @covers \App\Controllers\RouteController@funcAnyName 112 | */ 113 | public function testFuncAnyName() 114 | { 115 | $response = $this->request('GET', '/route/anyName/stelin', [], parent::ACCEPT_JSON); 116 | $response->assertExactJson(['stelin']); 117 | } 118 | } -------------------------------------------------------------------------------- /src/test/Cases/ValidatorControllerTest.php: -------------------------------------------------------------------------------- 1 | 19 | * @copyright Copyright 2010-2016 swoft software 20 | * @license PHP Version 7.x {@link http://www.php.net/license/3_0.txt} 21 | */ 22 | class ValidatorControllerTest extends AbstractTestCase 23 | { 24 | /** 25 | * @covers \App\Controllers\ValidatorController::string 26 | */ 27 | public function testString() 28 | { 29 | $response = $this->request('GET', '/validator/string/swoft', [], parent::ACCEPT_JSON); 30 | $response->assertExactJson(['boy', 'girl', 'swoft']); 31 | 32 | $response = $this->request('POST', '/validator/string/c', [], parent::ACCEPT_JSON); 33 | $response->assertExactJson(['message' => 'Parameter name length is too short (minimum is 3)']); 34 | 35 | $response = $this->request('POST', '/validator/string/swoft', ['name' => 'a'], parent::ACCEPT_JSON); 36 | $response->assertExactJson(['message' => 'Parameter name length is too short (minimum is 3)']); 37 | 38 | $response = $this->request('POST', '/validator/string/swoft?name=b', [], parent::ACCEPT_JSON); 39 | $response->assertExactJson(['message' => 'Parameter name length is too short (minimum is 3)']); 40 | 41 | $response = $this->request('POST', '/validator/string/swoft66666666', [], parent::ACCEPT_JSON); 42 | $response->assertExactJson(['message' => 'Parameter name length is too long (maximum is 10)']); 43 | 44 | $response = $this->request('POST', '/validator/string/swoft', ['name' => 'swoft66666666'], parent::ACCEPT_JSON); 45 | $response->assertExactJson(['message' => 'Parameter name length is too long (maximum is 10)']); 46 | 47 | $response = $this->request('POST', '/validator/string/swoft?name=swoft66666666', [], parent::ACCEPT_JSON); 48 | $response->assertExactJson(['message' => 'Parameter name length is too long (maximum is 10)']); 49 | 50 | $response = $this->request('POST', '/validator/string/swoftPath?name=swoftGet', ['name' => 'swoftPost'], parent::ACCEPT_JSON); 51 | $response->assertExactJson(['swoftGet', 'swoftPost', 'swoftPath']); 52 | } 53 | 54 | /** 55 | * @covers \App\Controllers\ValidatorController::number 56 | */ 57 | public function testNumber() 58 | { 59 | $response = $this->request('GET', '/validator/number/10', [], parent::ACCEPT_JSON); 60 | $response->assertExactJson([7, 8, 10]); 61 | 62 | $response = $this->request('POST', '/validator/number/3', [], parent::ACCEPT_JSON); 63 | $response->assertExactJson(['message' => 'Parameter id is too small (minimum is 5)']); 64 | 65 | $response = $this->request('POST', '/validator/number/6', ['id' => '-2'], parent::ACCEPT_JSON); 66 | $response->assertExactJson(['message' => 'Parameter id is not a number']); 67 | 68 | $response = $this->request('POST', '/validator/number/6', ['id' => '2'], parent::ACCEPT_JSON); 69 | $response->assertExactJson(['message' => 'Parameter id is too small (minimum is 5)']); 70 | 71 | $response = $this->request('POST', '/validator/number/6?id=-2', [], parent::ACCEPT_JSON); 72 | $response->assertExactJson(['message' => 'Parameter id is not a number']); 73 | 74 | $response = $this->request('POST', '/validator/number/6?id=2', [], parent::ACCEPT_JSON); 75 | $response->assertExactJson(['message' => 'Parameter id is too small (minimum is 5)']); 76 | 77 | $response = $this->request('POST', '/validator/number/12', [], parent::ACCEPT_JSON); 78 | $response->assertExactJson(['message' => 'Parameter id is too big (maximum is 10)']); 79 | 80 | $response = $this->request('POST', '/validator/number/9', ['id' => '12'], parent::ACCEPT_JSON); 81 | $response->assertExactJson(['message' => 'Parameter id is too big (maximum is 10)']); 82 | 83 | $response = $this->request('POST', '/validator/number/9?id=12', [], parent::ACCEPT_JSON); 84 | $response->assertExactJson(['message' => 'Parameter id is too big (maximum is 10)']); 85 | 86 | $response = $this->request('POST', '/validator/number/9?id=9', ['id' => '9'], parent::ACCEPT_JSON); 87 | $response->assertExactJson(['9', '9', 9]); 88 | } 89 | 90 | /** 91 | * @covers \App\Controllers\ValidatorController::float 92 | */ 93 | public function testFloat() 94 | { 95 | $response = $this->request('GET', '/validator/float/a', [], parent::ACCEPT_JSON); 96 | $response->assertExactJson(['message' => 'Parameter id is not float type']); 97 | 98 | $response = $this->request('GET', '/validator/float/5', [], parent::ACCEPT_JSON); 99 | $response->assertExactJson(['message' => 'Parameter id is not float type']); 100 | 101 | $response = $this->request('POST', '/validator/float/5.0', [], parent::ACCEPT_JSON); 102 | $response->assertExactJson(['message' => 'Parameter id is too small (minimum is 5)']); 103 | 104 | $response = $this->request('POST', '/validator/float/6.0', [], parent::ACCEPT_JSON); 105 | $response->assertExactJson(['message' => 'Parameter id is too big (maximum is 5)']); 106 | 107 | $response = $this->request('POST', '/validator/float/5.2', ['id' => 5], parent::ACCEPT_JSON); 108 | $response->assertExactJson(['message' => 'Parameter id is not float type']); 109 | 110 | $response = $this->request('POST', '/validator/float/5.2', ['id' => '5.0'], parent::ACCEPT_JSON); 111 | $response->assertExactJson(['message' => 'Parameter id is too small (minimum is 5)']); 112 | 113 | $response = $this->request('POST', '/validator/float/5.2', ['id' => '6.0'], parent::ACCEPT_JSON); 114 | $response->assertExactJson(['message' => 'Parameter id is too big (maximum is 5)']); 115 | 116 | $response = $this->request('POST', '/validator/float/5.2', ['id' => '5.2'], parent::ACCEPT_JSON); 117 | $response->assertExactJson([5.6, '5.2', 5.2]); 118 | 119 | $response = $this->request('POST', '/validator/float/5.2?id=5', [5.2], parent::ACCEPT_JSON); 120 | $response->assertExactJson(['message' => 'Parameter id is not float type']); 121 | 122 | $response = $this->request('POST', '/validator/float/5.2?id=5.0', [], parent::ACCEPT_JSON); 123 | $response->assertExactJson(['message' => 'Parameter id is too small (minimum is 5)']); 124 | 125 | $response = $this->request('POST', '/validator/float/5.2?id=6.0', [], parent::ACCEPT_JSON); 126 | $response->assertExactJson(['message' => 'Parameter id is too big (maximum is 5)']); 127 | 128 | 129 | $response = $this->request('POST', '/validator/float/5.2?id=5.2', ['id' => '5.2'], parent::ACCEPT_JSON); 130 | $response->assertExactJson(['5.2', '5.2', 5.2]); 131 | } 132 | 133 | /** 134 | * @covers \App\Controllers\ValidatorController::integer 135 | */ 136 | public function testInteger() 137 | { 138 | $response = $this->request('GET', '/validator/integer/10', [], parent::ACCEPT_JSON); 139 | $response->assertExactJson([7, 8, 10]); 140 | 141 | $response = $this->request('POST', '/validator/integer/3', [], parent::ACCEPT_JSON); 142 | $response->assertExactJson(['message' => 'Parameter id is too small (minimum is 5)']); 143 | 144 | $response = $this->request('POST', '/validator/integer/6', ['id' => 'a'], parent::ACCEPT_JSON); 145 | $response->assertExactJson(['message' => 'Parameter id is not integer type']); 146 | 147 | $response = $this->request('POST', '/validator/integer/6', ['id' => '2'], parent::ACCEPT_JSON); 148 | $response->assertExactJson(['message' => 'Parameter id is too small (minimum is 5)']); 149 | 150 | $response = $this->request('POST', '/validator/integer/6?id=a', [], parent::ACCEPT_JSON); 151 | $response->assertExactJson(['message' => 'Parameter id is not integer type']); 152 | 153 | $response = $this->request('POST', '/validator/integer/6?id=2', [], parent::ACCEPT_JSON); 154 | $response->assertExactJson(['message' => 'Parameter id is too small (minimum is 5)']); 155 | 156 | $response = $this->request('POST', '/validator/integer/12', [], parent::ACCEPT_JSON); 157 | $response->assertExactJson(['message' => 'Parameter id is too big (maximum is 10)']); 158 | 159 | $response = $this->request('POST', '/validator/integer/9', ['id' => '12'], parent::ACCEPT_JSON); 160 | $response->assertExactJson(['message' => 'Parameter id is too big (maximum is 10)']); 161 | 162 | $response = $this->request('POST', '/validator/integer/9?id=12', [], parent::ACCEPT_JSON); 163 | $response->assertExactJson(['message' => 'Parameter id is too big (maximum is 10)']); 164 | 165 | $response = $this->request('POST', '/validator/integer/9?id=9', ['id' => '9'], parent::ACCEPT_JSON); 166 | $response->assertExactJson(['9', '9', 9]); 167 | } 168 | 169 | /** 170 | * @covers \App\Controllers\ValidatorController::enum 171 | */ 172 | public function testEnum() 173 | { 174 | $response = $this->request('POST', '/validator/enum/4', [], parent::ACCEPT_JSON); 175 | $response->assertExactJson(['message' => 'Parameter name is an invalid enum value']); 176 | 177 | $response = $this->request('POST', '/validator/enum/1?name=4', [], parent::ACCEPT_JSON); 178 | $response->assertExactJson(['message' => 'Parameter name is an invalid enum value']); 179 | 180 | $response = $this->request('POST', '/validator/enum/1', ['name' => '4'], parent::ACCEPT_JSON); 181 | $response->assertExactJson(['message' => 'Parameter name is an invalid enum value']); 182 | 183 | $response = $this->request('POST', '/validator/enum/1?name=a', ['name' => '3'], parent::ACCEPT_JSON); 184 | $response->assertExactJson(['a', '3', '1']); 185 | } 186 | } -------------------------------------------------------------------------------- /src/test/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM swoft/swoft:latest 2 | 3 | MAINTAINER huangzhhui 4 | 5 | WORKDIR /var/www/swoft 6 | RUN composer install \ 7 | && composer dump-autoload -o \ 8 | && composer clearcache 9 | -------------------------------------------------------------------------------- /src/test/README.md: -------------------------------------------------------------------------------- 1 | # Automated Testing 2 | 3 | ## Unit test 4 | 5 | ### Start 6 | Docker Compose: `docker-compose up` 7 | 8 | ## Standard of Script 9 | 1. All `TestCase` should be extends `\Swoft\Test\AbstractTestCase` class -------------------------------------------------------------------------------- /src/test/bootstrap.php: -------------------------------------------------------------------------------- 1 | [ 20 | 'class' => \Swoft\Testing\Application::class, 21 | 'inTest' => true 22 | ], 23 | ]); 24 | 25 | $initApplicationContext = new \Swoft\Core\InitApplicationContext(); 26 | $initApplicationContext->init(); -------------------------------------------------------------------------------- /src/test/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | swoft-unittest: 4 | build: ./ 5 | container_name: swoft-unittest 6 | volumes: 7 | - ../:/var/www/swoft 8 | working_dir: /var/www/swoft/test 9 | command: ../vendor/bin/phpunit --bootstrap ./bootstrap.php --verbose ./ -------------------------------------------------------------------------------- /tars/tars.proto.php: -------------------------------------------------------------------------------- 1 | 'PHPTest', 5 | 'serverName' => 'swoft', 6 | 'objName' => 'obj', 7 | 'withServant' => true,//决定是服务端,还是客户端的自动生成 8 | 'jceFiles' => array( 9 | 'jce/example.jce' 10 | ), 11 | 'srcPath' => '',//这里用来autoload 12 | 'namespace' => '', 13 | ); --------------------------------------------------------------------------------