在上一篇《Spiral: 一个性能卓越的PHP/Golang混合开发框架》 中,我介绍了 Spiral 这个基于 PHP/Golang 的高性能混合开发框架,这次开始这个上手指南系列的第一篇文章。
TOC
我主要从事的是 WEB 开发工作,所以我就从 WEB 开发的角度来聊一下。
官方提供了 WEB 开发的项目骨架:spiral/app, 如果你想快速上手,可以从这个项目骨架开始:
安装
采用每个 PHPer 都很熟悉的 composer 来创建项目:
代码语言:txt复制composer create-project spiral/app myapp
项目创建之后,会自动执行一系列动作:
- 执行
php -r "copy('.env.sample', '.env')"
创建本地环境变量文件.env
- 执行
php app.php encrypt:key -m .env
向.env
文件中注入项目的唯一key
- 执行
php app.php configure -vv
确保当前项目被正确安装和配置,这个步骤会做的事情包括:- 创建并验证
runtime
目录权限,更新orm
,prototyped
,i18n
本地化语言包的缓存 - 将项目代码和视图模板中所有调用到的国际化字符提取到语言包文件中
- 预热视图缓存
- 更新依赖注入的标识与目标对象关系
- 创建并验证
- 下载
RoadRunner
的当前平台二进制文件
经过这一系列操作之后,你的本地项目就创建完成,可以立即开始体验或者进行开发了。
目录结构
官方项目骨架初始化得到的目录结构如下:
代码语言:txt复制myapp -- 项目目录
├── .env -- 环境变量配置文件
├── .rr.yaml -- 应用服务器配置文件
├── LICENSE -- 开源协议
├── README.md -- 说明文件
├── app -- 应用目录
│ ├── config -- 配置文件
│ │ └── database.php -- 数据库组件配置文件
│ ├── locale -- 语言包目录
│ │ ├── en -- 英文语言包
│ │ └── ru -- 俄语语言包
│ │ └── messages.en.php -- 俄语语言文件
│ ├── src -- 源码目录
│ │ ├── App.php -- 应用核心类
│ │ ├── Bootloader -- 引导加载器目录
│ │ │ ├── LocaleSelectorBootloader.php -- 用户语言识别加载器
│ │ │ ├── LoggingBootloader.php -- 日志加载器
│ │ │ └── RoutesBootloader.php -- 路由加载器
│ │ ├── Controller -- 控制器目录
│ │ │ └── HomeController.php -- 控制器类
│ │ ├── Job -- 任务目录
│ │ │ └── Ping.php 任务类
│ │ └── Middleware -- 中间件目录
│ │ └── LocaleSelector.php -- 语言识别中间件
│ └── views -- 视图目录
│ ├── embed -- 嵌入式视图(可以理解为页面片)目录
│ │ └── links.dark.php -- 嵌入式视图文件
│ ├── home.dark.php -- 视图文件
│ └── layout -- 布局目录
│ └── base.dark.php -- 基础布局文件
├── app.php -- 命令脚手架(开发辅助工具)
├── composer.json -- composer 配置文件
├── composer.lock -- composer 锁定文件
├── phpunit.xml -- phpunit 配置文件
├── public -- 网站根目录
│ ├── favicon.ico -- favicon
│ ├── images -- 图片目录
│ │ └── logo.svg -- LOGO 图片
│ └── styles -- 样式目录
│ └── welcome.css -- 样式文件
├── runtime -- 运行时目录(程序自动生成)
│ └── cache -- 缓存目录
│ ├── cycle.php -- Cycle ORM 缓存
│ ├── i18n.en.php -- 英语语言缓存
│ ├── i18n.locales.php -- 本地化语言缓存
│ └── prototyped.php -- 依赖注入缓存
├── spiral -- golang 开发的应用服务器(用来启动服务)
└── tests -- 测试文件目录
├── Feature -- 特性测试文件目录
│ └── BasicTest.php -- 特性测试示例
├── TestApp.php -- 用于测试的应用核心类
├── TestCase.php -- PHPUnitFrameworkTestCase 的扩展
├── Traits -- Traits 定义
│ ├── InteractsWithConsole.php -- 提供与 Console 命令交互的方法
│ └── InteractsWithHttp.php -- 提供与 HTTP 路由交互的方法
└── bootstrap.php -- 测试引导程序
由于项目团队目前的核心还是在 Framework
以及 RoadRunner
的开发迭代以及文档的编写上,所以这个 WEB 项目骨架还是不太完善的,绝对没有 Laravel
的那么舒服和合理。尤其是单元测试的部分,官方的骨架本来是没有集成 PHPUnit
的,我在第一次体验 Spiral 的时候,匆匆撸了一份提交 PR 过去,被接受了,但是显然就太简陋了。但是 Spiral 和 Symfony 一样,是允许你自由配置项目目录结构的,也可以不要官方提供的这个骨架,通过各个组件自由搭配你自己的框架(这个以后再说)。
运行服务器
项目初始化完成后,通过根目录下的 spiral
可执行文件,就能启动服务了:
./spiral serve -v -d
上述命令,--verbose, -v
等效,是输出详细信息,--debug, -d
是调试模式。除了 serve
子命令启动 HTTP 服务以外,还有 stop
子命令来停止服务,http:reset
重置 HTTP 服务的进程池,http:workers
查看 HTTP 服务工作进程。此外还有 GRPC 以及 JOB 相关的命令这里就不提了。可以自行通过 ./spiral help
或者 ./spiral -h
查看。
要说明的一点是,这个二进制文件不要加到代码仓库里,尤其是开发机、测试机、生产服务器操作系统不同的时候。因为它是根据你的平台操作系统下载的,你在 Mac 上开发,同一个二进制文件部署到 Linux 服务器就用不了了。
在部署代码的时候,需要执行一次 vendor/bin/spiral get-binary
命令,就会下载对应平台的二进制文件(如果你有多个 Spiral 项目部署在同一台机器,可以只下载一个二进制文件)。
服务启动以后,默认情况下,访问 http://localhost:8080
就会看到欢迎页面。
系统自带了三个路由,分别是:
/
(等效:/index.html
,/home/index
): 欢迎页面/home/ping
(等效:/ping.html
): 展示了队列任务(job)的基础用法/home/exception
(等效:/exception.html
): 展示开发模式下的错误调试页面
实际上系统还默认提供了一个系统运行指标服务,监听在 2112
端口,可以通过 Prometheus
访问 http://localhost:2112/metrics
监控系统指标,此处不多赘述。
如果你另外打开一个终端,执行 ./spiral http:/workers
, 会看到类似这样的一个表:
--------- ----------- --------- --------- --------------------
| PID | STATUS | EXECS | MEMORY | CREATED |
--------- ----------- --------- --------- --------------------
| 61067 | ready | 1 | 20 MB | 10 minutes ago |
| 61070 | ready | 1 | 18 MB | 10 minutes ago |
| 61071 | ready | 1 | 18 MB | 10 minutes ago |
| 61072 | ready | 1 | 18 MB | 10 minutes ago |
| 61073 | ready | 1 | 21 MB | 10 minutes ago |
| 61074 | ready | 1 | 18 MB | 10 minutes ago |
| 61075 | ready | 0 | 17 MB | 10 minutes ago |
| 61076 | ready | 0 | 17 MB | 10 minutes ago |
| 61077 | ready | 0 | 17 MB | 10 minutes ago |
| 61078 | ready | 0 | 17 MB | 10 minutes ago |
| 61079 | ready | 0 | 17 MB | 10 minutes ago |
| 61083 | ready | 0 | 17 MB | 10 minutes ago |
--------- ----------- --------- --------- --------------------
这里展示了你当前项目的所有工作进程的工作状况,如上图,我一共启动了 12 个工作进程(实际上默认还会有两个 jobs 进程)。这 12 个进程是采用轮询策略
顺序调度的,每一个新的请求都会交给下一个工作进程执行。默认情况下启动的 HTTP 工作进程数是你的 CPU 核数。
在本地开发的时候,建议使用单一工作进程,我们先来配置一下:
- 打开
.rr.yaml
文件 - 找到
http.workers
(即http:
下面的workers:
) - 在
command: "php app.php"
的下一行,加上两行:pool.numWorkers: 1
pool.maxJobs: 1
然后就可以进行开发了。与 swoole
系的框架相比,Spiral 的一大好处是除非你改动了诸如 App
, Bootloader
这类常驻内存的核心代码,否则你是不必重启服务的。像增加路由啊、增加数据实体啊一类的,跟常规的 PHP 程序的开发模式是没区别的,实时生效。
配置文件
官方骨架除了 .env
下面提供了 DEBUG=true
和 SAFE_MIGRATIONS=true
这两个需要在开发环境和生产环境调整的环境变量以外,只提供了一个 App/config/database.php
文件。
查找某个组件对应的配置文件名和可用配置项
实际上官方的每一个组件,都有自己的配置项是可以通过配置文件来调整配置的。但是骨架本身没有提供对应的配置示例,原因在于他们认为项目骨架已经提供了最优配置。当然,如果你需要的话,下面是如何查找某个组件的配置文件名以及可用配置项
的方法:
假如我们要配置一个 spiralcomponent
组件的配置文件名和配置项,那么你可以去 github.com/spiral/component
查阅该组件的文档(如果有文档的话),或者用下面的方法:
- 在
vendor
目录下找到spiral/component
子目录 - 展开这个目录,查找下面的
src/Config
目录,如果没有这个目录,那么这个组件就不支持配置文件配置。 - 在
vendor/spiral/component/src/Config
目录下,打开ComponentConfig.php
文件 - 你会看到
public const CONFIG = 'component'
这样的一行代码,说明这个组件的配置文件名是component.php
- 你还会看到
protected $config = []
这样的一个定义,这个数组就是该组件的可用配置项。
示例:修改项目的默认语言
掌握了这样的方法,比如我们要配置一下本地化组件,把默认语言改成 zh
:
- 打开
vendor/spiral/translator/src/Config/TranslatorConfig.php
- 通过这个文件,我们知道对应的配置文件是
translator.php
, 要配置的key
是locale
, 兼容语言的key
是fallbackLocale
,其它的配置项用默认的。 - 接下来,在
App/config
目录下创建translator.php
, 写入如下代码:
<?php
return [
代码语言:txt复制 'locale' => 'zh',
代码语言:txt复制 'fallbackLocale' => 'en'
];
代码语言:txt复制
就完成了对 Translator
组件的配置。
当然,实际上我们大多数时候只需要调整运行环境和数据库配置即可。
数据库配置
系统默认只提供了 sqlite
的数据库配置,但 Spiral 的数据库和 ORM 组件支持 MySQL, MariaDB, SQLite, PostgreSQL, SQLServer 等多种数据库,都提供了自动化数据库迁移(Migration)支持。
接下来我们要配置一下本地开发数据库,连接信息如下:
代码语言:txt复制Host: localhost
Port: 3306
Database: dev
User: dev
Password: dev
打开 App/config/database.php
文件,默认内容如下:
use SpiralDatabaseDriver;
return [
'default' => 'default',
'databases' => [
'default' => ['driver' => 'runtime'],
],
'drivers' => [
'runtime' => [
'driver' => DriverSQLiteSQLiteDriver::class,
'connection' => 'sqlite:' . directory('runtime') . 'runtime.db',
'profiling' => true,
],
]
];
这里的三个 key
,default
代表不指定的情况下使用的连接,databases
代表的是可用连接,而 drivers
代表的是可用数据库驱动。
注意!!Spiral 的
databases
实际上相当于其他框架一般用的connections
,而且在执行诸如migrate
一类的操作时,会在databases
中定义的所有连接上执行!!!
我们来增加一个 mysql
的配置:
use SpiralDatabaseDriver;
return [
'default' => 'default',
'databases' => [
'default' => ['driver' => 'mysql'],
],
'drivers' => [
'runtime' => [
'driver' => DriverSQLiteSQLiteDriver::class,
'connection' => 'sqlite:' . directory('runtime') . 'runtime.db',
'profiling' => true,
],
'mysql' => [
'driver' => DriverMySQLMySQLDriver::class,
'connection' => 'mysql:host=localhost;dbname=dev;charset=utf8mb4',
'username' => 'dev',
'password' => 'dev',
]
]
];
配置时采用的是 PDO 的 DSN 写法,需要了解更多的话可以查阅 Spiral 的官方文档或者 PHP PDO 的文档。
在下一篇文章,我会继续介绍 Spiral 的路由、控制器相关的部分。
至此我们就完成了开发前的基本配置。