oxygensuite/php-ast
Composer 安装命令:
composer require oxygensuite/php-ast
包简介
A lightweight Abstract Syntax Tree (AST) implementation for PHP, enabling structured parsing, analysis, and transformation of PHP code.
README 文档
README
A lightweight formula engine for PHP built on an Abstract Syntax Tree (AST). Parse, evaluate, and transform expressions with support for variables, functions, wildcards, and operator precedence.
Requirements
- PHP 8.4+
- ext-ctype
- ext-mbstring
Installation
composer require oxygensuite/php-ast
Quick Start
use OxygenSuite\PhpAst\Formulas\FormulaEvaluator; $evaluator = new FormulaEvaluator(); $data = [ 'lines' => [ ['quantity' => 2, 'unit_price' => 10.0, 'discount' => 0], ['quantity' => 3, 'unit_price' => 15.0, 'discount' => 5], ['quantity' => 1, 'unit_price' => 8.0, 'discount' => 0], ], ]; // Variable access (dot-notation) $evaluator->evaluate('lines.0.quantity', $data); // 2 // Arithmetic $evaluator->evaluate('lines.0.quantity * lines.0.unit_price', $data); // 20.0 // Wildcards $evaluator->evaluate('SUM(lines.*.quantity)', $data); // 6 // Functions $evaluator->evaluate('MAP(lines; quantity * unit_price - discount)', $data); // [20, 40, 8]
Variables
Variables use dot-notation for nested property access. Types are preserved (string, int, float, bool, null, array).
| Syntax | Resolves to |
|---|---|
uid |
$data['uid'] |
lines.0.quantity |
$data['lines'][0]['quantity'] |
a.b.c |
$data['a']['b']['c'] |
Variables can be used directly in expressions:
$evaluator->evaluate('lines.0.quantity * lines.0.unit_price', $data); $evaluator->evaluate('(base_price + tax) * quantity', $data);
Wildcards
The * wildcard extracts values across all items in an array.
// Single-level: lines.*.quantity → PLUCK(lines; "quantity") $evaluator->evaluate('lines.*.quantity', $data); // [2, 3, 1] // Multi-level: lines.*.taxes.*.amount → extracts all tax amounts from all lines $evaluator->evaluate('SUM(lines.*.taxes.*.amount)', $data);
Operators
Listed from highest to lowest precedence:
| Precedence | Operators | Description |
|---|---|---|
| 1 | ** |
Exponentiation |
| 2 | * / % |
Multiplication, division, modulo |
| 3 | + - |
Addition, subtraction |
| 4 | == != < > <= >= <=> |
Comparison |
| 5 | && |
Logical AND |
| 6 | || |
Logical OR |
| 7 | ?? ?: |
Null coalescing, elvis |
Parentheses override precedence: (a + b) * c.
Functions
All functions use semicolons (;) as argument separators.
Aggregation
| Function | Description | Example |
|---|---|---|
SUM(values) |
Sum of numeric values | SUM(lines.*.quantity) |
AVG(values) |
Average | AVG(lines.*.unit_price) |
MIN(values) |
Minimum value | MIN(lines.*.unit_price) |
MAX(values) |
Maximum value | MAX(lines.*.quantity) |
COUNT(values) |
Number of elements | COUNT(lines.*.quantity) |
Rounding
| Function | Description | Example |
|---|---|---|
ROUND(value; precision) |
Round to precision decimals | ROUND(10.567; 2) → 10.57 |
CEIL(value) |
Round up | CEIL(10.1) → 11 |
FLOOR(value) |
Round down | FLOOR(10.9) → 10 |
Array Manipulation
| Function | Description | Example |
|---|---|---|
PLUCK(array; "key") |
Extract column from array of objects | PLUCK(lines; "quantity") |
FLAT(array; depth) |
Flatten nested arrays (default depth: 1) | FLAT([[1,2],[3,[4,5]]]; 2) |
MAP(array; expr) |
Apply expression per item | MAP(lines; quantity * unit_price) |
FILTER(array; condition) |
Filter items by condition | FILTER(lines; unit_price > 10) |
GROUP(array; "key") |
Group items by key | GROUP(lines; "tax_category") |
SORT(array) |
Sort array | SORT(lines.*.quantity) |
JOIN(array; separator) |
Join into string | JOIN(lines.*.quantity; ",") |
FIRST(array) |
First element | FIRST(lines) |
LAST(array) |
Last element | LAST(lines) |
Conditional
| Function | Description | Example |
|---|---|---|
IF(cond; true_val; false_val) |
Conditional | IF(quantity > 10; "bulk"; "single") |
VALUE(array; "key") |
Get value by key | VALUE(line; "quantity") |
Composing Functions
Functions can be nested and combined with arithmetic:
// Sum of (quantity * unit_price) per line $evaluator->evaluate('SUM(MAP(lines; quantity * unit_price))', $data); // Filter then sum $evaluator->evaluate('SUM(PLUCK(FILTER(lines; tax_category == 1); "net_amount"))', $data); // Grouped aggregation $evaluator->evaluate('GROUP(lines; "tax_category")', $data); // → [1 => [...], 2 => [...], 3 => [...]] // Arithmetic on aggregated results $evaluator->evaluate('SUM(lines.*.net_amount) + SUM(lines.*.vat_amount)', $data);
Context Providers
For injecting external values (e.g., configuration, session data) into formula evaluation:
use OxygenSuite\PhpAst\ContextProvider\ContextProvider; class MyContext implements ContextProvider { public function getContextValue(string $key): mixed { return match ($key) { 'tax_rate' => 0.24, 'currency' => 'EUR', default => null, }; } } $evaluator = new FormulaEvaluator(new MyContext()); $evaluator->evaluate('unit_price * tax_rate', $data); // uses tax_rate from context
Context values take priority over data array values.
Custom Functions
Simple Function
Implement the Formula interface:
use OxygenSuite\PhpAst\AST\ASTEvaluator; use OxygenSuite\PhpAst\Formulas\Formula; readonly class DoubleFunction implements Formula { public function execute(array $arguments, array $data, ASTEvaluator $evaluator): float|int|string|array { return ($arguments[0] ?? 0) * 2; } }
AST-Aware Function
For functions that need per-item evaluation (like MAP/FILTER), implement ASTFormula instead. It receives raw AST nodes so you can evaluate expressions against each item:
use OxygenSuite\PhpAst\AST\ASTEvaluator; use OxygenSuite\PhpAst\Formulas\ASTFormula; readonly class MyTransform implements ASTFormula { public function execute(array $astNodes, array $data, ASTEvaluator $evaluator): mixed { [$itemsNode, $callbackNode] = $astNodes; $items = $itemsNode->accept($evaluator, $data); return array_map( fn($item) => $callbackNode->accept($evaluator, $item), $items, ); } }
Caching
Parsed ASTs are automatically cached per evaluator instance (default: 1000 entries). Repeated evaluation of the same formula string skips parsing entirely.
$evaluator->getCacheStats(); // ['hits' => 42, 'misses' => 10, 'size' => 10, 'hitRate' => 0.807] $evaluator->clearCache();
Error Handling
| Scenario | Behavior |
|---|---|
| Missing variable | Returns null |
| Division by zero | Returns 0 |
| Unknown function | Throws RuntimeException |
| Invalid expression | Throws RuntimeException |
| Recursion depth > 32 | Throws RuntimeException |
License
MIT
oxygensuite/php-ast 适用场景与选型建议
oxygensuite/php-ast 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 13 次下载、GitHub Stars 达 1, 最近一次更新时间为 2026 年 03 月 11 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「php」 「parser」 「ast」 「abstract syntax tree」 「code transformation」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 oxygensuite/php-ast 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 oxygensuite/php-ast 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 oxygensuite/php-ast 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Easy to use SDK with grabber for multiple platforms at once like YouTube, Dailymotion, Facebook and more.
Editable JSON AST with visitor traversal and formatting-preserving printing.
Parse Handlebars templates to a spec-compliant AST with PHP.
An MT940 bank statement parser for PHP
Laravel integration for the jsonapi.org parser
A modern HTML DOM parser for PHP using DOMDocument and Symfony CssSelector.
统计信息
- 总下载量: 13
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 2
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-03-11