3: 运行时配置

data/app.json 描述了 build,即被转译的内容。本章涵盖 runtime,即每个请求发生的事情。该配置位于 www/app.php(对于阶段/发布,位于 release/www/app.php)作为 phlo_app(...) 的参数。

<?php
require('/opt/phlo/phlo.php');
phlo_app (
	id:        'Example',
	host:      'dev.example.nl',
	auth:      true,
	build:     true,
	debug:     true,
	app:       '/var/www/example.nl/',
)

每个键都是一个 命名参数,同时也成为一个 PHP 常量,可以在你的应用程序中作为裸字(hostdatacomposer 等)随处使用。你自定义的键也是如此。

3.1: 身份和主机

默认 目的
id 应用的自由格式名称,由 Phlo Control Center、Phlo Dashboard 和日志使用
host null 此入口点允许运行的虚拟主机。Phlo 拒绝不匹配的请求,以避免意外的跨主机响应

3.2: 模式: `build`, `debug`, `auth`, `thread`

默认值 效果
build false 启用 build/lint/reflect CLI,并允许 Phlo 在每个请求中检测和重建更改的源文件
debug false 加载 debug.php,激活 debug() / dx() / 调试助手,提供完整的堆栈跟踪,而不是通用的 500 错误
auth false 使用 data/auth.ini 中的凭据进行全站 HTTP Basic 认证
thread false 工作模式(见 X.7),true = 无限,整数 = 每个工作线程的请求数量

请勿组合build: truethread: true。Build 在请求之间写入文件;在长时间运行的工作线程中这是不安全的。如果两者都开启,Phlo 会抛出运行时错误。

要求auth: true 需要 build: true。如果在未设置 build 的情况下设置了 auth,Phlo 在启动时会出错。(这是一个实现细节:全站认证处理程序在构建层中提供。为了保护非构建阶段的主机,请在 Phlo 前面的 Web 服务器中放置 HTTP Basic 认证。)

控制中心路径:当 build: truedebug: true 时,Phlo 控制中心会自动挂载在 /phlo,无需配置。使用可选的 control: 键将其挂载到不同的路径(control: 'admin'/admin 提供服务)或设置 control: false 以关闭它。在非构建+调试状态下,它始终处于关闭状态。

3.3: 路径

只有 app 是必需的。其余部分默认为 app 的子目录:

默认值 预期用途
app (必需) 应用根目录
data <app>/data/ 配置 (app.json, auth.ini)、凭据、运行时状态
php <app>/php/ 生成的 PHP,只有在发布输出位于其他位置时才更改此项
www <app>/www/ Web 根目录

您的发布入口点通常设置为 app: '<app>/release/'php: '<app>/release/',以便在不使用构建模式的情况下提供发布输出。

3.4: 控制中心和 WebSocket

默认值 效果
control 'phlo'build+debug 一起使用,其他情况下为 false 控制 UI 所在的 URL 前缀。例如 'beheer'/beheerfalse = 关闭
daemon null 此应用的 Phlo Daemon 端口。成为常量 daemon,由 wsCast() 和运行时助手使用

控制 UI 需要 build: true。有关 Phlo Daemon 设置,请参见 Daemon 和 WebSocket 章节。

3.5: Composer 自动加载

想要使用 vendor/ 中的 PHP 包吗?请提供路径:

phlo_app (
	composer: '/var/www/example.nl/',
	...
)

Phlo 然后注册一个 lazy autoloader,仅在需要解析未知类时加载 <composer>/vendor/autoload.php。如果您从未接触 Composer 包,则没有冷启动成本;一旦您使用它,就会获得完整的 Composer 自动加载。

约定: composer: '<app>/data/'composer.jsonvendor/ 然后位于 data/ 中,位于 webroot 之外)。

3.6: 跟踪和 CLI

默认值 效果
trace false 启用跟踪模式,参见 Trace 章节
cli 'php-zts'(如果是 ZTS)或 'php' Phlo 用于子进程(构建、任务、websocket)的 PHP 二进制文件路径。如果您的系统有非标准的 PHP 二进制文件,请覆盖此项

cli 在 v4 中是一个字符串(路径),而不是 v1 中的布尔值。

3.7: Worker模式规则

thread: true 将 Phlo 设置为长时间运行的工作模式(FrankenPHP, ReactPHP, RoadRunner)。运行时在请求之间保持在内存中。您需要了解三个规则:

1. 在 HTTP 路径中不要使用 die()exit() 两者都会终止整个工作进程。使用 return 或让终止调用(view()apply()location())发送响应。

2. 静态属性中不要有请求状态。 静态属性在工作进程中请求之间存活;请求 A 的用户数据会泄漏到请求 B 中。对于工作安全的缓存(类结构、计算的元数据),静态属性是可以的,但不适用于会话、用户、有效负载、时间或数据库状态。

3. 用 $objPers = true 标记长生命周期对象。 默认情况下,Phlo 在请求之间清除其实例映射。对于您明确希望重用的对象(数据库连接、预处理语句),设置 $this->objPers = true,以便清理时不影响它们。

3.8: 自定义键:您自己的常量

您传递给 phlo_app() 的每个额外命名参数都会自动成为一个 PHP 常量。这就是声明应用程序范围内路径或功能标志的方式:

phlo_app (
	app:      '/var/www/example.nl/',
	langs:    '/var/www/example.nl/langs/',
	files:    '/var/www/example.nl/files/',
	uploads:  '/var/www/example.nl/data/uploads/',
)

可以直接在 .phlo 中使用:

$dict = parse_ini_file(langs.'en.ini')
$path = files.'avatars/'.$user->id.'.jpg'
$url  = uploads

reflect::runtime 显示所有定义的常量。这对于在不打开 www/app.php 的情况下发现应用程序提供的内容非常有用。

3.9: 示例:开发和发布并排显示

phlo_app (
	id:        'Example',
	host:      'dev.example.nl',
	auth:      true,
	build:     true,
	debug:     true,
	trace:     true,
	app:       '/var/www/example.nl/',
	composer:  '/var/www/example.nl/data/',
	daemon:    3001,
	langs:     '/var/www/example.nl/langs/',
)
phlo_app (
	id:        'Example',
	host:      'example.nl',
	thread:    true,
	app:       '/var/www/example.nl/release/',
	php:       '/var/www/example.nl/release/',
	data:      '/var/www/example.nl/data/',
	composer:  '/var/www/example.nl/data/',
	daemon:    3001,
	langs:     '/var/www/example.nl/langs/',
)

开发者已经构建、调试、认证了控制中心和追踪。发布具有工作模式(thread),并将 webroot/php 输出指向 release/datacomposerlangs 保持不变,这是共享状态。

3.10: 请求和响应对象

两个运行时对象携带每个请求。%req(读取)和%res(写入)始终可用。

%req 计算属性:

属性 包含内容
%req->method HTTP 动词,转换为大写
%req->path 请求路径,不带前导斜杠
%req->part($i) 按索引获取路径段
%req->query 解析后的查询字符串数组
%req->async 当请求来自 phlo.js(SPA 导航,异步表单)时为 true
%req->cli 当从命令行运行时为 true
%req->secure, %req->scheme, %req->base, %req->url URL 部分,计算一次
%req->referer, %req->acceptLanguage 常见头部,已标准化

%res 表面:

成员 功能
%res->header($key, $value) 排队响应头(在渲染时发送)
%res->type 响应的 Content-Type
%res->text($body) / %res->json(...) / %res->xml($body) 设置主体(以及 json/xml 的类型);可链式调用
%res->render($code = null) 发送状态、头部和主体;标记响应完成
%res->streaming true 切换 apply() 为立即按命令刷新(见 WebSocket 章节)
%res->status, %res->done 状态码;输出是否已发送

output($content, $filename = null, $attachment = null, $file = null, $code = null, $type = null) 是用于文件、二进制大对象和带状态的 JSON 的响应函数:它提供一个文件(按名称的 mime,附加的 attachment 可选),或者当 $content 是数组时返回 JSON(output(['id' => $id], code: 201)output(['error' => 'not found'], code: 404));type 会覆盖预编码字符串主体的内容类型。view()/apply()/output()/error()/location() 是应用代码使用的响应函数;上面的 %res->json/text/xml/render 成员是它们构建的低级原语,用于少见的手动组装响应(自定义头部,特殊内容类型)。不要将它们包装在每个应用的 jsonOut()/respond() 辅助函数中。

课程。 die($content) 看起来像是“发送响应”,但它绕过了 render():排队的头部(包括 Content-Type)永远不会离开服务器,并且在工作模式下 die() 会终止整个工作进程。这个网站以 text/html 的形式提供其机器可读的端点已经好几周了。始终以 output(...)view()apply()location() 或显式的 %res->...->render() 结束。

运行时错误记录在 data/errors.json 中,以稳定的 8 字符引用 ID(主机、位置和去掉路径的消息的哈希)为键,这样相同的错误会去重为一个条目,并带有计数器和最后发生的时间戳。每个条目还记录了源映射的 .phlo 文件和行号、主机和请求路径;保留最新的 200 条。可以通过 reflect::errors [limit] 或在 Phlo Control Center 中读取它们。

该引用 ID 是用户与您之间的安全句柄:它会显示在生产错误页面上(Reference: a3f9c1d2),并在异步/JSON 响应的 error 负载中传递,因此用户可以引用它,您可以在 errors.json 中查找完整条目。生产页面永远不会打印消息或追踪;这些仅限于 debug

应用可以通过在其 app 类上声明一个静态的 errorPage(int $code, string $id, ?string $msg): string 来渲染自己的品牌错误页面。引擎会静态调用它,传入 HTTP 代码、模糊的引用 ID,以及真实的错误消息 仅在 debug(否则为 null),因此生产页面无法泄露内部信息,而调试环境可以在样式页面上显示消息。如果钩子抛出异常或返回空,引擎会回退到自己的页面:在 debug 下是诊断信息,其他情况下是最简页面。

我们使用必要的cookie来使该网站正常工作。在您的许可下,我们还使用分析工具来改善网站。