concept-labs/phtmal
Composer 安装命令:
composer require concept-labs/phtmal
包简介
(C)oncept-Labs Abstract HTML
关键字:
README 文档
README
Tiny, fluent HTML node tree with a minimal CSS-like selector engine — built to be lightweight, readable, and extensible. Designed for future integration with a layout package (name TBD) and for use in server-side rendering scenarios.
Highlights
- Fluent builder via
__call()($ul->li('A')->end()), with optional subtree callbacks- Pretty vs minified rendering
- Safe text nodes and explicit
raw()nodes- Normalized attributes (boolean attrs supported)
- Minimal CSS-like querying (tag,
*,#id,.class,[attr], combinators>+~,:first-child,:last-child,:nth-child)- Extensible: subclasses can override behavior and constants; interfaces define the contract
- NEW: Parse raw HTML into a Phtmal tree via
HtmlParserInterface+DomHtmlParser
Installation
Once published to Packagist:
composer require concept-labs/phtmal
For local/VCS use meanwhile:
Path repository (local dev):
{
"repositories": [
{ "type": "path", "url": "../phtmal" }
],
"require": {
"concept-labs/phtmal": "*"
}
}
VCS repository (GitHub):
{
"repositories": [
{ "type": "vcs", "url": "https://github.com/Concept-Labs/phtmal" }
],
"require": {
"concept-labs/phtmal": "dev-main"
}
}
Quick start
use Concept\Phtmal\Phtmal; $html = (new Phtmal('ul')) ->li(['class' => 'item'], function (Phtmal $li) { $li->span('A'); }) ->li('B')->end() ->top(); echo $html->render(); // pretty echo (string)$html; // minified
Attributes & boolean attributes:
$btn = (new Phtmal('button', 'Save')) ->class('btn', 'btn-primary') ->attr('disabled', ['disabled']); // short boolean form → <button disabled>…</button>
Text vs raw HTML:
$div = (new Phtmal('div'))->text('Safe <b>text</b>'); // escaped $div->raw('<b>UNSAFE</b>'); // unescaped (use with care)
Querying:
$items = $html->query('li.item:first-child, li.item:last-child'); $second = $html->queryOne('#main > .card:nth-child(2)');
HTML parsing (NEW)
You can parse raw HTML (documents or fragments) into a Phtmal tree using the parser interface.
Interfaces
HtmlParserInterface— contract:parseDocument(string $html, array $options = []): PhtmalNodeInterfaceparseFragment(string $html, string $containerTag = 'div', array $options = []): PhtmalNodeInterface
DomHtmlParser— DOMDocument-based implementation (tolerant to malformed HTML).
Usage
Parse a full document:
use Concept\Phtmal\DomHtmlParser; $parser = new DomHtmlParser(); $root = $parser->parseDocument('<!doctype html><html><body><div id="x">t</div></body></html>'); // $root is the <html> node echo $root->render(); // pretty echo (string)$root; // minified
Parse a fragment (no implied <html>/<body>):
$parser = new DomHtmlParser(); $list = $parser->parseFragment('<li>A</li><li class="x">B</li>', 'ul'); echo (string)$list; // <ul><li>A</li><li class="x">B</li></ul>
Scripts/styles are imported as RAW nodes (not escaped):
$parser = new DomHtmlParser(); $div = $parser->parseFragment('<script>if (a < b) { alert("x"); }</script>', 'div'); echo (string)$div; // <div><script>if (a < b) { alert("x"); }</script></div>
Custom factory (use your subclass of Phtmal):
class MyNode extends Concept\Phtmal\Phtmal {} $parser = new DomHtmlParser(fn(string $tag, ?string $text, array $attr) => new MyNode($tag, $text, $attr)); $tree = $parser->parseFragment('<span>Hello</span>', 'div');
Options
parseDocument() and parseFragment() accept the same $options array:
| Option | Type | Default | Description |
|---|---|---|---|
dropComments |
bool |
true |
Drop HTML comments. |
preserveWhitespace |
bool |
false |
Keep whitespace-only text nodes outside <pre>/<textarea>. |
preservePreWhitespace |
bool |
true |
Preserve whitespace in <pre> / <textarea>. |
encoding |
string |
'UTF-8' |
Input encoding hint for DOMDocument. |
rawTextTags |
string[] |
['script','style'] |
Treat content of these tags as RAW (unescaped). |
Interfaces (core)
The library is interface-first. Documentation primarily lives on interfaces; implementations use {@inheritDoc}.
PhtmalNodeInterface— node contract (fluent API, rendering, navigation, query integration).SelectorInterface— static querying:select(PhtmalNodeInterface $root, string $selector): array.HtmlParserInterface— parse raw HTML into a Phtmal tree.
Key guarantees:
- Implementations escape text on render (except explicit
#rawnodes). - Attributes are normalized to lists of strings, enabling predictable rendering and boolean-shortcuts.
- Children order is stable.
Core API (from PhtmalNodeInterface)
// Builder & structure __call(string $tag, array $args): PhtmalNodeInterface end(): PhtmalNodeInterface top(): PhtmalNodeInterface append(PhtmalNodeInterface|string $nodeOrText): static raw(string $html): static // Content & attributes text(?string $text): static attr(string $name, string|array|null $value = null): static id(string $id): static class(string ...$class): static data(string $key, string $value): static aria(string $key, string $value): static // Navigation & mutation parent(): ?PhtmalNodeInterface firstChild(): ?PhtmalNodeInterface nextSibling(): ?PhtmalNodeInterface cloneDeep(): PhtmalNodeInterface detach(): static replaceWith(PhtmalNodeInterface $node): PhtmalNodeInterface // Rendering render(bool $minify = false, int $indentLevel = 0): string // Querying query(string $selector): array queryOne(string $selector): ?PhtmalNodeInterface // Meta getTag(): string
Notes:
__call('li', [...])supports either(text, attrs)or(attrs, callback)— if a callback is the last argument, the method returns the parent (auto-jump back). Otherwise, it returns the new child (you can->end()manually).- Boolean attributes are rendered in short form if normalized as
['disabled' => ['disabled']].
Extensibility recommendations
- Overridable constants (protected):
VOID_ELEMENTS,INDENT,NL. - Overridable hooks (protected):
newNode(),escape(),renderAttributes(),_childrenRef(). - Open state (protected):
parent,children,tag,attributes,text.
Testing & QA
Install dev tools:
composer require --dev phpunit/phpunit:^10 phpstan/phpstan:^1.11
Run tests and static analysis:
vendor/bin/phpunit vendor/bin/phpstan analyse
License
MIT
concept-labs/phtmal 适用场景与选型建议
concept-labs/phtmal 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 9 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 08 月 08 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「php」 「html」 「abstract language」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 concept-labs/phtmal 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 concept-labs/phtmal 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 concept-labs/phtmal 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Texy converts plain text in easy to read Texy syntax into structurally valid (X)HTML. It supports adding of images, links, nested lists, tables and has full support for CSS. Texy supports hyphenation of long words (which reflects language rules), clickable emails and URL (emails are obfuscated again
A PHP Abstract Enum Class
PHP class to extend when building a WordPress plugin allowing you to follow smart plugin setup standards.
HTML and form generation
A modern HTML DOM parser for PHP using DOMDocument and Symfony CssSelector.
Reusable utilities library for Lacus Solutions' packages (type description, HTML escaping, random sequences)
统计信息
- 总下载量: 9
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 11
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-08-08