scottchiefbaker / yaml-polyfill
Pure-PHP polyfill for the PECL php-yaml extension: yaml_emit(), yaml_parse(), and friends (PHP 8.2+, zero dependencies)
Package info
github.com/scottchiefbaker/php-YAML-Polyfill
pkg:composer/scottchiefbaker/yaml-polyfill
Requires
- php: ^8.2
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A pure-PHP polyfill for the php-yaml extension, written for PHP 8.2+.
This library provides the same core API: yaml_emit(), yaml_parse(), etc.
It is a single, dependency-free PHP file, so projects that need simple,
reliable YAML input/output don't have to install a C extension.
It aims to cover roughly 90% of real-world YAML usage. Output is valid, readable YAML, but it is not guaranteed to be byte-identical to libyaml. If you need byte-exact fidelity to libyaml, use the php-yaml.
Requirements
- PHP 8.2+
Installation
Install with Composer:
composer require scottchiefbaker/yaml-polyfill
Or, if you'd rather not use Composer, drop the file somewhere and require it once:
require_once('/path/to/yaml-polyfill.php');
Usage
Emitting YAML
require 'yaml-polyfill.php'; $data = [ 'name' => 'example', 'version' => 1.0, 'tags' => ['a', 'b', 'c'], 'nested' => [ 'enabled' => true, 'retries' => 3, ], ]; echo yaml_emit($data);
Output:
--- name: example version: 1.0 tags: - a - b - c nested: enabled: true retries: 3 ...
Writing to and reading from files
yaml_emit_file('config.yml', $data); // returns bool $config = yaml_parse_file('config.yml'); // returns array $remote = yaml_parse_url('https://example.com/config.yml');
Parsing YAML
$yaml = "--- # A sample document name: example enabled: yes port: 8080 servers: - one.example.com - two.example.com description: > Multiple lines are folded into one. ..."; $data = yaml_parse($yaml); print_r($data);
Output:
Array
(
[name] => example
[enabled] => 1
[port] => 8080
[servers] => Array
(
[0] => one.example.com
[1] => two.example.com
)
[description] => Multiple lines are folded into one.
)
Features
yaml_emit($data, $encoding, $linebreak)- serialize nested arrays, scalars, and simple objects to block-style YAML. Alsoyaml_emit_file($filename, $data, ...).yaml_parse($input, $pos, &$ndocs, $callbacks)- parse plain, quoted, and block scalars, block mappings and sequences, single-line flow collections, comments, and multi-document streams (first document). Alsoyaml_parse_file($filename, ...)andyaml_parse_url($url, ...).- Handles string quoting, integers, floats (including
.inf/.nan), booleans, andnull. DateTimeInterfacevalues are serialized as ISO-8601 strings; objects are serialized viaget_object_vars();JsonSerializableobjects are serialized viajsonSerialize().- The
$encodingand$linebreakparameters are accepted for API parity; output is always UTF-8 with LF, CR, or CRLF line breaks. - Errors are intentional and well-behaved: parse/emit failures raise an
E_USER_WARNINGand returnfalse, matching PECL behavior rather than throwing exceptions. YAML_POLYFILLis defined (astrue) when this polyfill's implementations are the ones in use; it is never defined when the PECL extension is active, sodefined('YAML_POLYFILL')detects at runtime which library is providing theyaml_*()functions.- Zero dependencies: PHP 8.2+ core only, no extensions required.
Multi-document streams
Only the first document in a stream is parsed, matching the PECL
extension's behavior when $pos is 0.
Error handling
Parse errors do not throw; they raise an E_USER_WARNING and return
false (PECL behavior):
$result = yaml_parse("[unclosed"); if ($result === false) { // a warning has already been issued }
Limitations
This polyfill favors simplicity over full spec compliance. YAML Features not supported:
- Anchors, aliases, and merge keys (
&anchor,*alias,<<). - Tags (
!!str,!!binary,!!timestamp,!php/object, etc.), YAML 1.1 timestamps, and sexagesimal numbers. - Callbacks (the
$callbacksargument is ignored). - Multi-line plain and quoted scalars (continuation lines); multi-line flow collections (flow must be on a single line).
- Block scalar keep-chomping (
+|,+>). - Complex mapping keys (
? key) and explicit key indicators. - Tab indentation.
- Empty arrays always emit as
[]; empty maps and empty lists are not distinguished. - No anchors/tags/callbacks on emit; no flow style; no control over indent unit or line width.
- Byte-exact output parity with libyaml is not a goal.
$posis ignored;$ndocsis always 1; only the first document is read.- UTF-16 output is not produced;
$encodingis ignored.
Testing
This library contains extensive unit tests. At the time of this writing there are over 130 unit tests. This helps maintain the quality and robustness of the library. Run the test suite from the repository root:
php unit_tests.php [--filter PATTERN]
License
GPL-2.0.