Spiral 详细上手指南之安装与配置

本文首发于云加社区我的个人专栏。受云加社区协议限制,未经许可不得转载。关于 Spiral 框架的这个系列文章,都会首发云加社区,之后过一段时间才会同步到个人博客。

在上一篇《Spiral: 一个性能卓越的PHP/Golang混合开发框架》 中,我介绍了 Spiral 这个基于 PHP/Golang 的高性能混合开发框架,这次开始这个上手指南系列的第一篇文章。

我主要从事的是 WEB 开发工作,所以我就从 WEB 开发的角度来聊一下。

官方提供了 WEB 开发的项目骨架:spiral/app, 如果你想快速上手,可以从这个项目骨架开始:

安装

采用每个 PHPer 都很熟悉的 composer 来创建项目:

composer create-project spiral/app myapp

项目创建之后,会自动执行一系列动作:

  1. 执行 php -r "copy('.env.sample', '.env')" 创建本地环境变量文件 .env
  2. 执行 php app.php encrypt:key -m .env.env 文件中注入项目的唯一 key
  3. 执行 php app.php configure -vv 确保当前项目被正确安装和配置,这个步骤会做的事情包括:
    1. 创建并验证 runtime 目录权限,更新 orm, prototyped, i18n 本地化语言包的缓存
    2. 将项目代码和视图模板中所有调用到的国际化字符提取到语言包文件中
    3. 预热视图缓存
    4. 更新依赖注入的标识与目标对象关系
  4. 下载 RoadRunner 的当前平台二进制文件

经过这一系列操作之后,你的本地项目就创建完成,可以立即开始体验或者进行开发了。

目录结构

官方项目骨架初始化得到的目录结构如下:

myapp -- 项目目录
├── .env -- 环境变量配置文件
├── .rr.yaml -- 应用服务器配置文件
├── LICENSE -- 开源协议
├── README.md -- 说明文件
├── app -- 应用目录
│   ├── config -- 配置文件
│   │   └── database.php -- 数据库组件配置文件
│   ├── locale -- 语言包目录
│   ├── 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 -- 网站根目录
├── runtime -- 运行时目录(程序自动生成)
│   └── cache -- 缓存目录
├── spiral -- golang 开发的应用服务器(用来启动服务)
└── tests -- 测试文件目录
    ├── Feature -- 特性测试文件目录
    │   └── BasicTest.php -- 特性测试示例
    ├── TestApp.php -- 用于测试的应用核心类
    ├── TestCase.php -- PHPUnit\Framework\TestCase 的扩展
    ├── 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 核数。

在本地开发的时候,建议使用单一工作进程,我们先来配置一下:

  1. 打开 .rr.yaml 文件
  2. 找到 http.workers(即 http: 下面的 workers:)
  3. command: "php app.php" 的下一行,加上两行:
    • pool.numWorkers: 1
    • pool.maxJobs: 1

然后就可以进行开发了。与 swoole 系的框架相比,Spiral 的一大好处是除非你改动了诸如 App, Bootloader 这类常驻内存的核心代码,否则你是不必重启服务的。像增加路由啊、增加数据实体啊一类的,跟常规的 PHP 程序的开发模式是没区别的,实时生效。

配置文件

官方骨架除了 .env 下面提供了 DEBUG=trueSAFE_MIGRATIONS=true 这两个需要在开发环境和生产环境调整的环境变量以外,只提供了一个 App/config/database.php 文件。

查找某个组件对应的配置文件名和可用配置项

实际上官方的每一个组件,都有自己的配置项是可以通过配置文件来调整配置的。但是骨架本身没有提供对应的配置示例,原因在于他们认为项目骨架已经提供了最优配置。当然,如果你需要的话,下面是如何查找某个组件的配置文件名以及可用配置项的方法:

假如我们要配置一个 spiral\component 组件的配置文件名和配置项,那么你可以去 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, 要配置的 keylocale, 兼容语言的 keyfallbackLocale,其它的配置项用默认的。
  • 接下来,在 App/config 目录下创建 translator.php, 写入如下代码:
<?php

return [
    'locale' => 'zh',
    'fallbackLocale' => 'en',
];

就完成了对 Translator 组件的配置。

当然,实际上我们大多数时候只需要调整运行环境和数据库配置即可。

数据库配置

系统默认只提供了 sqlite 的数据库配置,但 Spiral 的数据库和 ORM 组件支持 MySQL, MariaDB, SQLite, PostgreSQL, SQLServer 等多种数据库,都提供了自动化数据库迁移(Migration)支持。

接下来我们要配置一下本地开发数据库,连接信息如下:

Host: localhost
Port: 3306
Database: dev
User: dev
Password: dev

打开 App/config/database.php 文件,默认内容如下:

use Spiral\Database\Driver;

return [
    'default'   => 'default',
    'databases' => [
        'default' => ['driver' => 'runtime'],
    ],
    'drivers'   => [
        'runtime' => [
            'driver'     => Driver\SQLite\SQLiteDriver::class,
            'connection' => 'sqlite:' . directory('runtime') . 'runtime.db',
            'profiling'  => true,
        ],
    ]
];

这里的三个 keydefault 代表不指定的情况下使用的连接,databases 代表的是可用连接,而 drivers 代表的是可用数据库驱动。

注意!!Spiral 的 databases 实际上相当于其他框架一般用的 connections,而且在执行诸如 migrate 一类的操作时,会在 databases 中定义的所有连接上执行!!!

我们来增加一个 mysql 的配置:

use Spiral\Database\Driver;

return [
  'default' => 'default',
  'databases' => [
    'default' => ['driver' => 'mysql'],
  ],
  'drivers' => [
    'runtime' => [
      'driver' => Driver\SQLite\SQLiteDriver::class,
      'connection' => 'sqlite:' . directory('runtime') . 'runtime.db',
      'profiling' => true,
    ],
    'mysql' => [
      'driver' => Driver\MySQL\MySQLDriver::class,
      'connection' => 'mysql:host=localhost;dbname=dev;charset=utf8mb4',
      'username' => 'dev',
      'password' => 'dev',
    ]
  ]
];

配置时采用的是 PDO 的 DSN 写法,需要了解更多的话可以查阅 Spiral 的官方文档或者 PHP PDO 的文档。

在下一篇文章,我会继续介绍 Spiral 的路由、控制器相关的部分。

至此我们就完成了开发前的基本配置。