EN | NL | 中文

1: 介绍

Phlo 是一种编程语言和引擎,基于 PHP 8+,旨在构建紧凑、清晰和高性能的 web 应用程序。路由、控制器代码、视图、样式和前端更新形成一个整体。Phlo 将 .phlo 转换为普通的 PHP 类,并生成所需的资产。

Web 服务器指向你的 webroot /www。未知路径被重写为 /www/app.php,在这里 Phlo 读取你的配置,管理实例并处理路由。构建阶段在源文件更改时 自动 (JIT) 运行。

1.1: 哲学

1.2: 什么是Phlo

Phlo 是一个 PHP 的超集,具有自动构建功能。一个 .phlo 文件可以包含:

Phlo 是模块化的,可以用于:全栈、仅前端引擎、类编写/代码生成或作为资产管道。

1.3: 安装

1) 放置引擎

将文件夹 phlo/ 放入你的项目中(在 /www 之外)。

2) Webserver → webroot /www

将 webserver 设置为 文档根目录为 /www 并将未知路径重写为 app.php

Nginx

server {
    root /路径/到/项目/www;

    location / {
        try_files $uri $uri/ /app.php?$query_string;
    }
}

Apache (.htaccess 在 /www)

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ app.php [QSA,L]

静态文件(图片,app.jsapp.css)将直接提供;只有未知路径会转到 Phlo。

3) /www/app.php 的内容

使用 有效的入口点 如在你的代码库中:

<?php
require('/srv/phlo/phlo.php');
phlo_app_jsonfile($app = dirname(__DIR__).'/', "$app/data/app.json");

这将执行:

4) 构建 (JIT) 和脚本

1.4: 项目结构

一个 Phlo 项目有一个固定的结构:

/www/              ← webroot (公开)
  app.php          ← 中央入口点
  app.js           ← 自动生成的前端包
  app.css          ← 自动生成的 CSS

/data/app.json     ← 必需的配置

/phlo/             ← Phlo 引擎
/php/              ← 转换后的 PHP (自动)

重要事项:

2: 配置

每个 Phlo 应用都有一个 必需 的配置文件:

/data/app.json

引擎从 app.php 中读取此文件,并据此确定资源、库、打包和资产输出。

2.1: 目标和位置

2.2: 最低配置

{
  "id": "MijnApp",
  "version": ".1",
  "host": "localhost",
  "dashboard": "phlo",
  "debug": true,
  "build": {
    "libs": []
  }
}

为什么这样?

我们稍后将单独处理没有(完整)构建的生产/发布。

2.3: `build.sources`

仅在您想要的源路径比应用路径 /www/app.php 更多时需要。

{
  "build": {
    "sources": [
      "%app/",
      "/srv/phloCMS/",
      "/srv/phloCMS/fields/"
    ],
    "libs": []
  }
}

2.4: `构建.库`

声明你希望预先加载并在项目中可识别的库(来自 phlo/libs/)。

{
  "build": {
    "libs": [
      "DB/DB",
      "DB/MySQL",
      "model",
      "payload"
    ]
  }
}

2.5: 命名空间和资产

使用仅当您想要发送捆绑/资产范围时

{
  "build": {
    "libs": [],
    "defaultNS": "app",
    "phloNS": ["app", "cms"],
    "iconNS": ["cms"],
    "icons": "/srv/icons"
  }
}

2.6: 前端构建选项

{
  "build": {
    "libs": [],
    "phloJS": false,
    "buildCSS": true,
    "minifyCSS": false,
    "buildJS": true,
    "minifyJS": false
  }
}
类型 意义
phloJS 布尔 打包Phlo前端引擎(高级用例)。
buildCSS 布尔 处理来自.phlo的样式并写入CSS资产(按命名空间)。
minifyCSS 布尔 压缩CSS。
buildJS 布尔 打包前端脚本并写入JS资产(按命名空间)。
minifyJS 布尔 压缩JS。

重要: Phlo写入/www/的所有内容(如app.jsapp.css 任何命名空间/额外资产)都是生成的,并在构建时被覆盖。不要手动编辑。

2.7: 其他字段

3: 语法与结构

Phlo 是一个 PHP 的超集,具有紧凑的无分号语法。在一个 .phlo 文件中,你可以组合路由、属性、方法、视图、样式、脚本和控制器代码。构建器会转译为普通的 PHP/JS/CSS。

3.1: 文件结构

顶级元素:

最小有效示例:

route GET home => $this->main

prop title = '欢迎'

method main => view($this->home)

view home:
<h1>$this->title</h1>

3.2: 控制器代码

顶级语句在块外形成文件的 控制器
控制器在实例存在后运行(不在 __construct 中)——这防止了循环引用。

示例(无害的初始化):

prop initialized = false
$this->initialized = true

3.3: 声明

示例:

if ($active) $count = $count + 1

foreach ($rows AS $r) $sum = $sum + $r->value

foreach ($rows AS $r){
  $sum = $sum + $r->value
  $n = $n + 1
}

chunk (
  title: '概述',
  main: view($this->home),
)

apply (
  title: '完成',
  main: '<p>准备好了</p>',
)

3.4: 变量与作用域

3.5: 常量

精确如引擎中定义:

常量 意义 / 值
phlo 当前 Phlo 版本(字符串)
cli 如果没有 REQUEST_METHOD 则为 true(CLI)
async 如果 HTTP_X_REQUESTED_WITH 等于 'phlo' 则为 true
method 'CLI' 或请求的 HTTP 方法
jsonFlags JSON_PRETTY_PRINT JSON_UNESCAPED_UNICODE JSON_UNESCAPED_SLASHES
br '<br>'
bs '\\'(反斜杠)
bt '`'(反引号)
colon ':'
comma ','
cr "\r"
dash '-'
dot '.'
dq '"'(双引号)
eq '='
lf "\n"
nl cr.lf → 实际上是 "\r\n"
perc '%'
pipe ' '`'
qm '?'
semi ';'
slash '/'
space ' '
sq "'"(单引号)
tab "\t"
us '_'
void ''(空字符串)

这些常量在 .phlo 中随处可用。

3.6: 字符串与运算符

字符串:'single'"double"
运算符:符合 PHP。Phlo 添加了更紧凑的语法(箭头主体,命名参数);语义保持不变。

3.7: 功能

功能是 项目全局 并写入 /php/app.php

单行:

function add($a, $b) => $a + $b

多行:

function sum($a, $b){
  return $a + $b
}

3.8: 方法

方法属于从 .phlo 文件生成的类。

method hello($who) => '嗨 '.$who

method classify($x) {
  if ($x > 5) return '大'
  return '小'
}

箭头用于单行逻辑;多行使用大括号。

3.9: 道具

静态(转译为 PHP 类属性;不允许函数调用):

prop title = '应用'
prop defaults = ['theme' => '黑暗']

计算属性(惰性 + 缓存):

prop now => time()
prop fullName => $this->first.' '.$this->last

带参数的属性(仅计算):

prop repeat($n) => str_repeat('*', $n)

# 使用
$this->repeat(5)

3.10: 静力学

定义:

static x = 1
static y => time()

同一类中调用:

dx (
  static::$x,
  static::x(),
  static::y,
)

外部(通过类名)调用:

dx (
  test::$x,
  test::x(),
  test::y,
)

重要:

3.11: 命名参数

完全支持;使调用显式且减少错误。

%MySQL->delete (
  'Users',
  'id=?',
  id: 1,
)

3.12: 错误处理

3.13: 风格规则

4: 路由

在 Phlo 中,路由将一个 以空格分隔的路径 + HTTP 方法 关联到一个 目标(通常是一个方法)。来自所有 .phlo 文件的路由被收集;路由器通过 app::route() 激活。

4.1: 基础形式

路由 [异步|两者] [GET|POST|PUT|DELETE|PATCH] 填充 [填充2 ...] => 目标

示例:

路由 GET 主页 => $this->main
方法 main => 视图($this->home)

4.2: 同步 / 异步 / 两者皆可

关键词 行为
(省略) 同步 (普通 HTTP)
异步 异步 (来自 Phlo-前端的请求)
两者 同步 异步均可
route 两者 GET 数据 => $this->loadData
route 异步 POST 项目 保存 => $this->saveItems

4.3: 变量

Phlo 解析每个路径段。以 $ 开头的段是 变量,具有额外的功能:

4.3.1 必需(传递给目标)

route GET user $id => $this->showUser($id)
method showUser($id) => view($this->profile)

4.3.2 可选存在 使用 ?布尔值

route GET search $full? => $this->search($full)

4.3.3 剩余(可变长度)使用 =*

route GET file $path=* => $this->serveFile($path)

4.3.4 默认值 使用 =

route GET page $slug=home => $this->page($slug)

4.3.5 长度要求 使用 .N

route GET code $pin.6 => $this->enter($pin)

4.3.6 选择列表 使用 :a,b,c

route GET report $range:daily,weekly,monthly => $this->report($range)

你可以 组合 这些形式。示例:

# 枚举 + 必需 id
route GET export $fmt:csv,json $id => $this->export($fmt, $id)

# 枚举 + 默认
route GET theme $name:light,dark=light => $this->theme($name)

4.4: 有效载荷检查与 `@`

您指定了带有一个 @确切 body-keys 和 逗号分隔 列表。路由器将其与 %payload 中的键进行 逐一比较(确切的集合;顺序与引擎提供的相同)。

route POST user @name,email => $this->createUser

method createUser => dx(%payload->name, %payload->email)

Body-keys 作为方法参数绑定;您通过 %payload 读取它们。

4.5: 目标

本地方法

route GET profile show => $this->show
method show => view($this->profile)

外部类方法(静态)

route GET api version $major => api::getVersion($major)

4.6: 激活路由器

路由仅在之后匹配:

app::route()

例如,将此调用放在app.phlo(或其他中央控制器)中,在应用初始化之后和404处理的回退之前。

4.7: 推荐结构

5: 视图

在 Phlo 中,你可以直接在 .phlo 文件中定义视图。视图是一个以 view 开头的命名或匿名块,包含 HTML(加上最小的 Phlo 结构)。

5.1: 声明

5.2: 论点

视图可以有 参数(包括默认值):

view($x = 0):
<p>值: $x</p>

view detail($input):
<p>输入: $input</p>

调用:

method show => view($this->detail('abc'))
method show2 => view($this->view(5))

与方法一样,一旦提供参数,括号是必需的。

5.3: 单行和多行

5.4: 速记HTML

紧凑的HTML简写会自动转换:

# shorthand
<p#id.class1.class2/>

# equivalent
<p id="id" class="class1 class2"></p>

5.5: 变量和表达式

5.5.1 直接变量和 单一属性

你可以 直接 在视图中写:

view($name):
<p>你好 $name,现在是 $this->time。</p>

直接允许:普通变量和 单一 属性访问(如 $this->time)。 不允许 在 HTML 中直接使用链式访问或函数/方法调用。

5.5.2 函数、方法、链式 或复杂表达式

使用 表达式标记

view($x = 1):
<p>{{ $this->call('test') }}</p>
<p>{( $x > 1 ? '多个' : '一个' )}</p>
<p>{{ $this->members->all }}</p>

(我们在这里故意不对这两种形式施加额外的语义;两者都用于内联表达式。)

5.6: 属性值

属性值 可以不加引号 如果它们 不包含 空格、@ 或变量:

view:
<p title=correct>正确答案</p>
<a href=/test1 data-value="$this->value">链接</a>
<a href=/test2 data-value="{{ $this->compute('value') }}">链接</a>

5.7: 声明

使用 标签 在 HTML 中进行控制流:

view:
<p>列表:</p>
<foreach $this->list AS $key => $value>
  <p>项目:$key</p>
  <if $value > 1>
    <p>高值:$value</p>
  <elseif $value === 1>
    <p>正好 1:$value</p>
  <else>
    <p>其他值:$value</p>
  </if>
</foreach>

5.8: 查看渲染

一个视图 通过 view($this->Naam)(或无名的 view作为调用渲染。 这个调用 发送输出结束脚本apply() 也是如此。

route GET home => $this->home

method home => view($this->home)

view home:
<h1>$this->title</h1>

不要这样做

# ❌ 错误 – 视图“连接在一起”是不存在的;第一个调用结束。
method dashboard {
  view($this->header)
  view($this->content)
}

如果你想要多个输出片段:创建一个视图 来合并它们,或者在视图内部构建。

5.9: 最佳实践

6: CSS

Phlo 使用一种紧凑的、不带分号的 CSS 语法在 <style> 块中。 你写的规则使用 冒号 作为分隔符:

规则:

6.1: `<style>`块

<style>
html: height: 100dvh
body {
  background: #947b6c
  font-family: Sans-serif
  p: line-height: 2em
}
</style>

输出(概念):

html { height: 100dvh; }
body { background: #947b6c; font-family: Sans-serif; }
body p { line-height: 2em; }

6.2: 网络与群体

带有双点的链;用逗号分组 — 完整上下文 将应用于每个项目。

<style>
body: h1, p: \:first-letter: color: green
</style>

输出:

body h1:first-letter,
body p:first-letter { color: green; }

6.3: 媒体查询在选择器中

你可以在选择器块内编写 @media (…) ,Phlo 会将其移动到正确的位置并保留选择器上下文:

<style>
h1 {
  color: white
  @media (max-width: 768px): color: black
}
</style>

输出:

h1 { color: white; }
@media (max-width: 768px){
  h1 { color: black; }
}

6.4: 变量

Phlo 支持 CSS 变量 通过 $namen。 你可以在 :root 中定义变量,或者在任何其他级别 — 但 :root 通常用于全局主题。

<style>
:root {
  $background: #0d0d0d
  $surface: #1a1a1a
  $text: #ffffff
  $accent: #ff4a00
}

body {
  background: $background
  color: $text
}

button {
  background: $accent
  color: $text
}
</style>

输出

:root {
  --background: #0d0d0d;
  --surface: #1a1a1a;
  --text: #ffffff;
  --accent: #ff4a00;
}

body {
  background: var(--background);
  color: var(--text);
}

button {
  background: var(--accent);
  color: var(--text);
}

👉 Phlo 自动将 $variabelen 转换为 --custom-properties 并在调用时使用 var(--...)。 你可以在任何地方重用变量 — 也包括在媒体查询和嵌套选择器中。

6.5: 动态变量

Phlo的前端引擎包含库 DOM/CSS.var,通过它你可以在CSS中定义的 $变量 直接从JavaScript访问和修改,通过全局的 app.var 对象。

每个 $变量 在你的CSS中会自动在 app.var.<名称> 下可用。

示例

<style>
:root {
  $background: #0d0d0d
  $text: #ffffff
}
</style>

<script>
app.var.background = '#000000'
const textColor = app.var.text
</script>

👉 这些修改在浏览器中 实时 生效,并直接影响所有使用该变量的元素。

你可以用它来:

工作原理

6.6: 完整示例

body {
  background: #947b6c;
  font-family: Sans-serif;
}
body h1:first-letter,
body p:first-letter {
  color: green;
}
body p {
  line-height: 2em;
}
h1 {
  color: white;
}
html {
  height: 100dvh;
}
p {
  color: navy;
}
p:last-child {
  color: yellow;
}
@media (max-width: 768px){
  h1 {
    color: black;
  }
}

6.7: 最佳实践

7: 对象关系映射

Phlo包含一个强大的内置ORM,可以将数据库表定义为类。
模型可以通过columns快速定义,或通过声明式schema进行详细定义。
记录被视为instances,支持属性、方法、视图、关系和多种数据库引擎。

7.1: 基本原则

一个 ORM 模型是一个 .phlo 文件,包含:

示例:

@ class: user
@ extends: model

view => $this->name

static table = 'users'
static columns = 'id,name,email,active,created'

7.2: 定义模型

7.2.1 使用 columns 的表(快速且轻量)

使用 columns 来创建简单的表格:

@ class: shipment
@ extends: model

view: $this->destination ($this->user)

static table = 'shipments'
static order = 'changed DESC'
static columns = 'id,user,destination,costs,valid,weight,shipped,created,changed'
static objParents = ['user' => 'user']
@ class: user
@ extends: model

view => $this->name

static table = 'users'
static order = 'changed DESC'
static columns = 'id,name,email,level,active,created,changed'
static objChildren = ['shipments' => 'shipment']

7.2.2 使用 schemafield(...)(丰富且声明式)

使用 schema 一次性定义字段、关系和用户界面:

@ class: shipment
@ extends: model

view: $this->destination ($this->user)

static table = 'shipments'
static schema => arr (
    id: field (type: 'token', length: 4, title: 'ID'),
    destination: field (type: 'text', required: true, search: true),
    user: field (type: 'parent', obj: 'user', required: true),
    costs: field (type: 'price', prefix: '€ '),
    valid: field (type: 'bool'),
    attachments: field (type: 'child', obj: 'attachment', list: true),
)
@ class: user
@ extends: model

view => $this->name

static table = 'users'
static schema => arr (
    id: field (type: 'token'),
    name: field (type: 'text', search: true, required: true),
    email: field (type: 'email', required: true),
    shipments: field (type: 'child', obj: 'shipment'),
    groups: field (type: 'many', obj: 'group', table: 'user_groups'),
)

schema 在与 PhloCMS 结合使用时尤其强大,但也可以独立使用。

7.3: 增删改查

# 获取
$user = user::record(id: 1)
$list = shipment::records(order: 'created DESC')

# 创建
$shipment = shipment::create(destination: '巴黎', user: 1)

# 编辑 & 保存
$shipment->destination = '里昂'
$shipment->objSave

# 删除
shipment::delete('id=?', $shipment->id)

7.4: 关系导航

关系通过属性可用:

类型 声明 使用
parent type: parent $shipment->user
child type: child $user->shipments
many type: many $user->groups

多对多

type: many 使用一个中间表:

groups: field (
    type: 'many',
    obj: 'group',
    table: 'user_groups',
)

导航:

$user = user::record(id: 1)
foreach ($user->groups as $group)
  echo $group->title

关系被批量加载以提高性能。没有跨数据库连接;每个类从其自己的引擎加载。

7.5: 实例动态

每个记录都是你模型类的真实实例
你可以使用属性、方法和视图来添加虚拟字段、计算或表示:

@ class: shipment
@ extends: model

prop summary => $this->destination.' ('.$this->user.')'
method tax => $this->costs * 0.21

view:
<p>$this->summary</p>
<p>{( $this->tax )}</p>

使用:

$shipment = shipment::record(id: 'AB12')
echo $shipment->summary
echo $shipment   # 使用视图作为字符串

属性和方法始终作用于记录实例,而不是静态的。

7.6: 过滤和查询

所有查询方法都接受命名参数和类似SQL的过滤器:

shipment::records(destination: '巴黎')
shipment::records(where: 'valid=1 AND weight>10')
shipment::pair(columns: 'id,destination')

支持:whereordergroupjoins,缓存和模式感知列。

7.7: 缓存和性能

ORM使用内部缓冲区(objRecordsobjLoaded)进行关系查找,并通过以下方式进行可选的APCu缓存

static objCache = true       # 1天
# 或
static objCache = 600        # 10分钟

记录和关系按批次加载。 在循环中使用records()进行批量选择,而不是使用record()

7.8: 多个引擎

Phlo 支持通过 prop DB 多个后端。 默认是 %MySQL,但你可以为每个模型设置任何引擎。

SQLite

prop DB => %SQLite(data.'users.db')
@ class: notes
@ extends: model

prop DB => %SQLite(data.'notes.db')
static table = 'notes'
static columns = 'id,title,body'

PostgreSQL

prop DB => %PostgreSQL
@ class: invoices
@ extends: model

prop DB => %PostgreSQL
static table = 'invoices'
static columns = 'id,customer_id,total,created'

不同引擎上的表可以在关系中组合;每个类获取自己的数据。


/data/creds.ini

对于 MySQL 和 PostgreSQL 等引擎,你可以将凭据放在:

/data/creds.ini
[mysql]
host     = localhost
database = db_name
user     = db_user
password = db_password

[postgresql]
host     = localhost
database = my_pg_db
user     = pg_user
password = pg_pass

Phlo 会通过 %creds->... 自动加载这些。

7.9: 功能概述

功能 / 属性 类型 描述
record(...) 静态 获取1条记录(或null)
records(...) 静态 获取多条记录(数组)
create(...) 静态 插入 + 获取
objSave 实例 插入或更新
delete(where, …) 静态 删除
pair, item, column 静态 快速查询助手
objParents / schema: parent 声明性 父关系
objChildren / schema: child 声明性 子关系
schema: many 声明性 多对多
objCache 静态 可选的 APCu 缓存
prop DB 静态 每个模型引擎

7.10: 最佳实践

8: 实例管理

Phlo使用自己的实例管理器来高效且可预测地初始化和重用对象。该系统决定何时执行控制器代码,如何存储实例以及如何防止循环引用。

8.1: 基础解释

当你定义一个 .phlo 文件时,它会在构建阶段转换为一个类。 通过 %naam 对对象的每次调用都通过 实例管理器 (phlo()/phlo/phlo.php 中) 进行。

示例:

prop title = '欢迎'

route GET home => $this->main

method main => view($this->home)

view home:
<h1>$this->title</h1>

当路由 /home 被调用时:

  1. 实例管理器检查是否已经存在该类的实例。
  2. 如果没有,则 创建并保存 该实例。
  3. 创建后将执行 控制器代码 (见 §8.2)。
  4. 然后调用请求的方法。

8.2: 控制器代码

所有在 .phlo 文件中属于 routepropstaticmethodfunctionview<style><script> 的代码都是 控制器代码
这段代码将在 实例化后 执行,一旦实例完全存在。

示例:

prop ready = false

%session->start()   # 控制器代码(顶层)
$this->ready = true

8.3: `__handle()`的角色

Phlo 为每个类生成一个特殊的 __handle() 方法。
该方法由实例管理器在 通过 %naam 请求实例时 调用。

__handle()

您无需自己调用或覆盖 __handle() — 它是生成的类和实例管理器的一部分。

8.4: 懒惰初始化

因为控制器代码 在构造后 执行,实例可以 相互引用 而不会发生不必要的递归创建。

示例:

# file a.phlo
prop message = 'A ready'

# file b.phlo
prop message = 'B ready'

# file main.phlo
route GET test => $this->show

method show {
  dx(%a->message, %b->message)
}

8.5: 最佳实践

9: 工具和命令行接口

Phlo拥有一个非常轻量级的工具链。不需要外部编译器或CLI框架:一切都在/phlo/中的Phlo引擎本身上运行。在请求期间,Phlo会自动处理生成的PHP、JS和CSS文件的构建和更新。你可以手动启动这个过程以进行CI/CD或预发布构建,但在正常设置中并不需要。

9.1: 构建过程

Phlo 将 .phlo 文件转译为 PHP、JS 和 CSS。 这发生在:

入口点:

在每个请求中,Phlo 会检查:

  1. 源文件是否有更改,
  2. 生成的文件是否是最新的,
  3. 如有必要,执行增量构建。

9.2: 命令行接口

Phlo 不需要外部 CLI 框架;你可以直接使用 php。 对于特殊情况(预构建、CI、暂存),你可以手动构建:

php -r "require 'phlo/build.php'; phlo_build();"

或者从自己的 PHP 脚本中:

<?php
require 'phlo/build.php';
phlo_build();

这将经历与运行时相同的构建过程,但在 请求上下文之外

所以没有 phlo CLI 命令或包。你只需使用 PHP 本身。

9.3: 调试模式

调试模式在 data/app.json 中设置,方法如下:

{
  "debug": true
}

在调试模式下:

9.4: 部署

为了生产:

  1. data/app.json 中设置 "debug": false
  2. 手动执行 phlo_build() 以便所有文件都已预先转译。
  3. /www/ 文件夹上线(包括 app.phpapp.jsapp.css)。
  4. 确保 /php/ 文件夹中的生成后端代码一起迁移。

Phlo 不依赖于 npm、webpack 或其他工具链。 所有工具都内置并直接在 PHP 下运行。

9.5: 最佳实践


✅ 正确解释构建过程(JIT + 通过 phlo_build() 手动) ✅ 没有虚假的CLI命令 ✅ debug模式如同在app.json中 ✅ 部署如Phlo实际执行的那样 ✅ 正确处理 /www/app.js/www/app.css(绝不要手动修改)

10: 翻译

Phlo 内置了对 多语言和动态翻译 的支持。引擎包含功能和库,使您可以 在线翻译 文本,应用语言切换,并 异步加载翻译 而不打断用户体验。

10.1: 语言助手

Phlo 提供了最常用语言的简短助手函数,可以直接在视图和代码中使用:

在视图中的示例:

view:
<p>{( nl('Hallo wereld') )}</p>
<p>{( en('Hello world') )}</p>

语言助手:

10.2: 其他使用

对于动态翻译,Phlo 提供了两个核心功能:translate()translation()

translate()

<p>{( translate('welcome_message') )}</p>

translation()

<p>{( translation('dynamic_intro_text') )}</p>

10.3: 动态语言选择

主动语言可以通过前端动态设置和更改。 当用户切换语言时,UI会自动重新翻译而无需重新加载。

典型流程:

  1. 应用以默认语言(例如 nl)启动。
  2. 用户选择另一种语言。
  3. 前端引擎切换语言代码。
  4. 通过 translation() 加载的文本将在新语言可用时重新翻译
  5. 通过 nl()en() 等助手加载的文本将保持其固定值。

10.4: 最佳实践

11: 高级

Phlo被设计为一个模块化系统。你可以单独使用引擎的部分,结合现有项目或扩展自己的功能,而无需修改核心。

11.1: 模块化使用

Phlo 可以作为 完整框架 使用,也可以作为 部分 使用。
例如:

示例:在静态网站中仅使用前端

<script src="/app.js" defer></script>

然后调用 Phlo 前端功能,如 app.apply()app.state,而不使用 .phlo 后端。

或者:将 Phlo 集成到现有的 PHP 应用程序中,仅在 sources 中添加几个 .phlo 文件。
Phlo 会将它们转译到 /php/,然后你可以直接使用生成的类。

11.2: 集成

你可以通过以下方式将 Phlo 集成到现有代码库中:

  1. 将 Phlo 引擎放在子目录中,例如 /vendor/phlo/
  2. app.php 添加为所有不存在路由的中央路由器。
  3. app.json 中补充 build.sources 字段,添加你现有代码的路径,以及 Phlo 目录。

示例 data/app.json

{
  "id": "LegacyApp",
  "version": ".1",
  "host": "localhost",
  "dashboard": "phlo",
  "debug": true,
  "build": {
    "libs": ["session", "json"],
    "sources": [
      "%app/",
      "/legacy/phlo/"
    ]
  }
}

这样你可以保留现有的 PHP 代码,同时添加 .phlo 文件。 Phlo 会对其进行转译并将其添加到你的项目中,而无需重构整个结构。

11.3: 最佳实践

12: 附件

附件包含现成的示例项目模板额外的展示,展示了Phlo在实践中的应用。
本部分旨在作为参考资料和灵感来源——而不是作为主要文档。

12.1: 代码示例

一个小而易读的.phlo片段集合,展示了常用模式:

基本路由与视图

prop title = '欢迎'

route GET home => $this->main

method main => view($this->home)

view home:
<h1>$this->title</h1>

带变量的路由

route GET user $id => $this->show($id)

method show($id) {
  $user = %users->record(id: $id)
  view($this->profile, $user)
}

view profile($user):
<h1>$user->name</h1>

异步翻译

view:
<p>{( translation('welcome_text') )}</p>

12.2: 项目模板

一个最小的项目结构,包含所有必需的部分:

/www/
  app.php       ← 中央入口点
  app.js        ← 生成的前端包
  app.css       ← 生成的CSS
/data/
  app.json      ← 必需的配置
/phlo/          ← Phlo引擎
/php/           ← 转换后的后端代码(自动) 
/app/           ← 你的Phlo源文件 (*.phlo)

这是推荐的基础结构。 额外的sources可以在data/app.json中定义,如果你想组合多个源路径。

12.3: CSS 展示

一个 Phlo 紧凑 CSS 语法的视觉示例:

输入

<style>
html: height: 100dvh
body {
  background: #947b6c
  font-family: Sans-serif
  p: line-height: 2em
}
body: h1, p: \:first-letter: color: green
h1 {
  color: white
  @media (max-width: 768px): color: black
}
p {
  color: navy
  \:last-child: color: yellow
}
</style>

输出

body {
  background: #947b6c;
  font-family: Sans-serif;
}
body h1:first-letter,
body p:first-letter {
  color: green;
}
body p {
  line-height: 2em;
}
h1 {
  color: white;
}
html {
  height: 100dvh;
}
p {
  color: navy;
}
p:last-child {
  color: yellow;
}
@media (max-width: 768px){
  h1 {
    color: black;
  }
}

12.4: ORM模型

典型的 ORM 类型定义示例在 Phlo 中:

type users {
  static columns = null

  field(id, type: number, auto: true)
  field(name, type: text)
  field(email, type: text)
}

route GET users => $this->overview

method overview {
  foreach (%users->records(order: 'name') as $u)
    dx($u->id, $u->name)
}

仅获取记录:

$user = %users->record(id: 1)
dx($user->name)

12.5: 进一步的资源