渐进式 PHP 7 不仅仅是常驻框架引擎
这是一个 QueryPHP 应用,其核心框架可以在这里找到 Framework。
QueryPHP 是一款现代化的渐进式高性能 PHP 7 不仅仅是常驻框架,以工程师用户体验为历史使命,让每一个 PHP 应用都有一个好框架。
百分之百单元测试覆盖直面 Bug 一剑封喉,基于 Zephir 实现框架常驻,依托 Swoole 生态实现业务常驻,此刻未来逐步渐进。 我们的愿景是 USE LEEVEL WITH SWOOLE DO BETTER, 让您的业务撑起更多的用户服务。
代码如诗,自由如风, 此刻携手 QueryPHP 共创美好.
QueryPHP 基于一款成立于 2010 年的 PHP 框架 DoYouHaoBaby 开发,继承了上一代产品的优秀之处,彻底革新并进行了长达 2 年重构.
核心包
QueryPHP 框架 PHP 工程化实践
如何安装
基本使用
composer create-project hunzhiwange/queryphp myapp dev-master
打开浏览器访问
php leevel server
连接数据库
首先创建一个数据库.
CREATE DATABASE IF NOT EXISTS myapp DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
修改 .env
vim .env
...
// Database
DATABASE_DRIVER = mysql
DATABASE_HOST = 127.0.0.1
DATABASE_PORT = 3306
DATABASE_NAME = queryphp_development_db
DATABASE_USER = root
DATABASE_PASSWORD =
...
to
...
// Database
DATABASE_DRIVER = mysql
DATABASE_HOST = 127.0.0.1
DATABASE_PORT = 3306
DATABASE_NAME = myapp
DATABASE_USER = root
DATABASE_PASSWORD = 123456
...
执行数据库迁移命令
php leevel migrate:migrate
php leevel server
测试连接数据库
{
count: 4,
:trace: {
...
}
}
登陆到 QueryVue 后台
安装前端
第一步安装前端,细节信息可以在 frontend/README.md 查看.
cd frontend
npm install -g cnpm --registry=https://registry.npm.taobao.org // Just once
cnpm install
npm run serve # npm run dev
登陆后台
user: admin
password: 123456
运行测试
首先创建一个用于测试的数据库 test.
CREATE DATABASE IF NOT EXISTS test DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
修改 .testing
vim .testing
...
// Database
DATABASE_DRIVER = mysql
DATABASE_HOST = 127.0.0.1
DATABASE_PORT = 3306
DATABASE_NAME = test
DATABASE_USER = root
DATABASE_PASSWORD =
...
to
...
// Database
DATABASE_DRIVER = mysql
DATABASE_HOST = 127.0.0.1
DATABASE_PORT = 3306
DATABASE_NAME = test
DATABASE_USER = root
DATABASE_PASSWORD = 123456
...
执行数据库迁移命令
php leevel migrate:migrate -e testing
运行
_____________ _______________
______/ \__ _____ ____ ______ / /_ _________
____/ __ / / / / _ \/ __`\/ / __ \/ __ \/ __ \___
__/ / / / /_/ / __/ / \ / /_/ / / / / /_/ /__
\_\ \_/\____/\___/_/ / / .___/_/ /_/ .___/
\_\ /_/_/ /_/
$cd /data/codes/queryphp/
$vim .testing # modify database redis and other
$php leevel migrate:migrate -e testing
- $php vendor/bin/phpunit
+ $php ./build/phpunit
生产环境优化
关闭调试
修改 .env 或者 runtime/bootstrap/option.php.
// Environment production、testing and development
ENVIRONMENT = production
// Debug
DEBUG = false
DEBUG_JSON = false
DEBUG_CONSOLE = false
DEBUG_JAVASCRIPT = false
执行优化指令
下面的指令可以让 QueryPHP 运行得更加快速。
php leevel router:cache
php leevel option:cache
php leevel i18n:cache
php leevel view:cache
php leevel autoload (Equivalent to `composer dump-autoload --optimize --no-dev`)
或者
php leevel production
开发阶段
打开调试
修改 .env 或者 runtime/bootstrap/option.php.
// Environment production、testing and development
ENVIRONMENT = development
// Debug
DEBUG = true
DEBUG_JSON = true
DEBUG_CONSOLE = true
DEBUG_JAVASCRIPT = true
清理缓存指令
php leevel i18n:clear
php leevel log:clear
php leevel option:clear
php leevel router:clear
php leevel session:clear
php leevel view:clear
php leevel autoload --dev (Equivalent to `composer dump-autoload --optimize`)
Or
php leevel development
安装 Leevel 扩展让性能更好
Windows
后续会提供 dll 扩展.
Linux
从下面的仓库下载源代码.
git clone git@github.com:hunzhiwange/leevel.git
cd ext
GCC 编译源码.
$/path/to/phpize
$./configure --with-php-config=/path/to/php-config
$make && make install
将扩展添加到你的 php.ini, 使用 php -m 查看扩展是否被安装.
extension = leevel.so
使用 swoole 提升性能
Http 服务
php leevel http:server # php leevel http:server -d
php leevel http:reload
php leevel http:stop
php leevel http:status
Swoole http 和 php-fpm 保持一致
root@vagrant-ubuntu-10-0-2-5:/data/codes/queryphp# php leevel http:server
_____________ _______________
______/ \__ _____ ____ ______ / /_ _________
____/ __ / / / / _ \/ __`\/ / __ \/ __ \/ __ \___
__/ / / / /_/ / __/ / \ / /_/ / / / / /_/ /__
\_\ \_/\____/\___/_/ / / .___/_/ /_/ .___/
\_\ /_/_/ /_/
Http Server Version 1.0.0
+-----------------------+---------------------------------+
| Item | Value |
+-----------------------+---------------------------------+
| host | 0.0.0.0 |
| port | 9501 |
| process_name | leevel.http |
| pid_path | @path/runtime/protocol/http.pid |
| worker_num | 8 |
| daemonize | 0 |
| enable_static_handler | 1 |
| document_root | @path/www |
| task_worker_num | 4 |
+-----------------------+---------------------------------+
Websocket 服务
php leevel websocket:server # php leevel websocket:server -d
php leevel websocket:reload
php leevel websocket:stop
php leevel websocket:status
一个聊天室测试
root@vagrant-ubuntu-10-0-2-5:/data/codes/queryphp# php leevel websocket:server
_____________ _______________
______/ \__ _____ ____ ______ / /_ _________
____/ __ / / / / _ \/ __`\/ / __ \/ __ \/ __ \___
__/ / / / /_/ / __/ / \ / /_/ / / / / /_/ /__
\_\ \_/\____/\___/_/ / / .___/_/ /_/ .___/
\_\ /_/_/ /_/
Websocket Server Version 1.0.0
+-----------------+--------------------------------------+
| Item | Value |
+-----------------+--------------------------------------+
| host | 0.0.0.0 |
| port | 9502 |
| process_name | leevel.websocket |
| pid_path | @path/runtime/protocol/websocket.pid |
| worker_num | 8 |
| daemonize | 0 |
| task_worker_num | 4 |
+-----------------+--------------------------------------+
Rpc 服务
php leevel rpc:server # php leevel rpc:server -d
php leevel rpc:reload
php leevel rpc:stop
php leevel rpc:status
Rpc thrift 协议
namespace php Leevel.Protocol.Thrift.Service
/**
* ---------------------------------------------------------------
* 定义一个请求包结构
* ---------------------------------------------------------------
*
* 约定请求数据包,方便只定义一个结构全自动调用 MVC 服务
*/
struct Request
{
// call 为字符串类型,是指 Service 接口的名称
// 例如:home:blog/info@get 为调用 mvc 接口中的数据
1: required string call;
// params 为 list 类型数据,一个元素可重复的有序列表,C++ 之 vector,Java 之 ArrayList,PHP 之 array
2: list params;
// 服务端客户端共享自定义共享数据
// 相当于 PHP 中的关联数组
3: map metas;
}
/**
* ---------------------------------------------------------------
* 定义一个响应包结构
* ---------------------------------------------------------------
*
* 通用响应接口,数据以 JSON 进行交互
*/
struct Response
{
// status 为响应状态,200 表示成功,其他参考 HTTP 状态
1: required i16 status;
// code 为 JSON 字符串,客户端自主进行解析
2: required string data;
}
/**
* ---------------------------------------------------------------
* 定义一个通用的服务
* ---------------------------------------------------------------
*
* 通用调用服务,通过一个 call
*/
service Thrift
{
Response call(1: Request request)
}
一个 rpc 测试
root@vagrant-ubuntu-10-0-2-5:/data/codes/queryphp# php leevel rpc:server
_____________ _______________
______/ \__ _____ ____ ______ / /_ _________
____/ __ / / / / _ \/ __`\/ / __ \/ __ \/ __ \___
__/ / / / /_/ / __/ / \ / /_/ / / / / /_/ /__
\_\ \_/\____/\___/_/ / / .___/_/ /_/ .___/
\_\ /_/_/ /_/
Rpc Server Version 1.0.0
+-----------------------+--------------------------------+
| Item | Value |
+-----------------------+--------------------------------+
| host | 0.0.0.0 |
| port | 1355 |
| process_name | leevel.rpc |
| pid_path | @path/runtime/protocol/rpc.pid |
| worker_num | 8 |
| daemonize | 0 |
| dispatch_mode | 1 |
| open_length_check | 1 |
| package_max_length | 8192000 |
| package_length_type | N |
| package_length_offset | 0 |
| package_body_offset | 4 |
| task_worker_num | 4 |
+-----------------------+--------------------------------+
declare(strict_types=1);
/*
* This file is part of the your app package.
*
* The PHP Application For Code Poem For You.
* (c) 2018-2099 http://yourdomian.com All rights reserved.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\App\Controller\Api;
use Leevel\Http\IResponse;
use Leevel\Protocol\Proxy\Rpc as Rpcs;
/**
* rpc tests.
*
* @author Name Your
*
* @since 2018.08.31
*
* @version 1.0
*/
class Rpc
{
/**
* 默认方法.
*
* @return \Leevel\Http\IResponse
*/
public function handle(): IResponse
{
return Rpcs::call('api/rpc/rpc-result', ['foo', 'bar'], ['arg1' => 'hello', 'arg2' => 'world']);
}
/**
* RPC 结果.
*
* @return array
*/
public function rpcResult(string $arg1, string $arg2, array $metas): array
{
return ['arg1' => $arg1, 'arg2' => $arg2, 'metas' => $metas];
}
}
// The result
// {"arg1":"foo","arg2":"bar","metas":{"arg1":"hello","arg2":"world"}}
RoadRunner 支持
RoadRunner 是一个开源的高性能 PHP 应用服务器、负载均衡器和流程管理器。它支持作为一个服务运行,能够在每个项目的基础上扩展其功能。
安装 RoadRunner
你可以下载二进制文件.
cd /data/server
wget https://github.com/spiral/roadrunner/releases/download/v1.3.5/roadrunner-1.3.5-darwin-amd64.zip
unzip roadrunner-1.3.5-darwin-amd64.zip
cd /data/codes/queryphp
Roadrunner 服务
/data/server/roadrunner-1.3.5-darwin-amd64/rr serve -d -v # -d = debug
/data/server/roadrunner-1.3.5-darwin-amd64/rr http:reset
/data/server/roadrunner-1.3.5-darwin-amd64/rr http:workers -i
Roadrunner 和 php-fpm 保持一致
root@vagrant-ubuntu-10-0-2-5:/data/codes/queryphp# /data/server/roadrunner-1.3.5-darwin-amd64/rr serve -d -v
DEBU[0000] [static]: disabled
DEBU[0000] [rpc]: started
DEBU[0000] [http]: started
INFO[0060] 127.0.0.1 {23.1ms} 200 GET http://127.0.0.1:9601/api/test
统一团队代码风格
安装 PHP 代码格式化工具
不需要安装即可使用,我们已经下载了版本。
基本使用
$cd /data/codes/queryphp
- $php-cs-fixer fix --config=.php_cs.dist
+ $./build/php-cs-fixer fix --config=.php_cs.dist
使用 Git 钩子
添加一个 pre-commit 钩子.
cp ./build/pre-commit.sh ./.git/hooks/pre-commit
chmod 777 ./.git/hooks/pre-commit
跳过钩子
# git commit -h
# git commit -n -m 'pass hook' #bypass pre-commit and commit-msg hooks
PHPStan 静态分析
php ./build/phpstan analyse
致谢
感谢同事 毛飞 在开发这个项目过程中的无私帮助,让我有了很多新的认识, 这让 QueryPHP 变得更加的美好.
也非常感谢下面的这些优秀的开源软件, 我们也参考了很多的设计与思想, 让我们可以站在巨人的肩膀上保持创新.
版权协议
QueryPHP 是一个基于 MIT license 授权许可协议的开源软件.