定制 maxi-format/maxi 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

maxi-format/maxi

最新稳定版本:0.1.0

Composer 安装命令:

composer require maxi-format/maxi

包简介

PHP library for parsing and dumping MAXI schema

README 文档

README

PHP 8.0+ library for parsing and dumping MAXI schema + records.

Version: 0.1.0

Install

composer require maxi-format/maxi

API overview

Method Description
Maxi::parse($input, $options) Parse MAXI text → MaxiParseResult (schema + raw records)
Maxi::stream($input, $options) Parse schema eagerly, yield records lazily via PHP generator
Maxi::parseAs($input, $classMap, $options) Parse + hydrate records into class instances
Maxi::parseAutoAs($input, $classes, $options) Same, with alias inferred from #[MaxiType] attributes
Maxi::dump($data, $options) Serialize objects / parse results → MAXI text
Maxi::dumpAuto($objects, $options) Same, with schema inferred from #[MaxiType]/#[MaxiField] attributes

All methods are also available as standalone functions in the Maxi\Api namespace (e.g. Maxi\Api\parseMaxi()).

Documentation

  • docs/parser.md — full parser guide: Maxi::parse, Maxi::stream, Maxi::parseAs, Maxi::parseAutoAs, hydration, reference resolution, options
  • docs/dumper.md — full dumper guide: Maxi::dump, Maxi::dumpAuto, schema-annotated classes, references, inheritance, options

Quick start

Parse

use Maxi\Maxi;

$input = <<<MAXI
U:User(id:int|name|email)
###
U(1|Julie|julie@maxi.org)
U(2|Matt|matt@maxi.org)
MAXI;

$result = Maxi::parse($input);

echo $result->records[0]->values[1]; // 'Julie'
echo $result->schema->getType('U')->name; // 'User'

Parse into class instances

use Maxi\Maxi;
use Maxi\Attribute\MaxiType;
use Maxi\Attribute\MaxiField;

#[MaxiType(alias: 'U', name: 'User')]
class User
{
    #[MaxiField(typeExpr: 'int', id: true)]
    public int $id;

    #[MaxiField(required: true)]
    public string $name;

    #[MaxiField(annotation: 'email')]
    public ?string $email = null;
}

$result = Maxi::parseAutoAs($input, [User::class]);

$user = $result->data['U'][0];
echo $user->name;  // 'Julie'
echo $user->email; // 'julie@maxi.org'

Or with an explicit alias → class map:

$result = Maxi::parseAs($input, ['U' => User::class]);

Dump

Round-trip from a parse result:

$maxi = Maxi::dump($result);

From PHP objects with auto-detected schema:

$maxi = Maxi::dumpAuto([
    new User(id: 1, name: 'Julie', email: 'julie@maxi.org'),
]);

With explicit type definitions:

use function Maxi\Api\dumpMaxi;

$maxi = dumpMaxi([['id' => 1, 'name' => 'Julie']], [
    'defaultAlias' => 'U',
    'types' => [[
        'alias'  => 'U',
        'name'   => 'User',
        'fields' => [
            ['name' => 'id', 'typeExpr' => 'int'],
            ['name' => 'name'],
        ],
    ]],
]);

Stream (lazy record parsing)

For large files, use streaming to avoid loading all records into memory at once. The schema is parsed eagerly; records are yielded one at a time via a PHP generator:

$stream = Maxi::stream($input);

echo $stream->schema->getType('U')->name; // 'User'

foreach ($stream as $record) {
    echo $record->alias;     // 'U'
    echo $record->values[1]; // field values
}

stream() also accepts a file handle (resource):

$fh     = fopen('data.maxi', 'r');
$stream = Maxi::stream($fh);

PHP Attributes — Doctrine-style annotations

Map MAXI types to PHP classes using native PHP 8 Attributes:

use Maxi\Attribute\MaxiType;
use Maxi\Attribute\MaxiField;

#[MaxiType(alias: 'O', name: 'Order')]
class Order
{
    #[MaxiField(typeExpr: 'int', id: true)]
    public int $id;

    #[MaxiField(typeExpr: 'U')]
    public int|User $user;

    #[MaxiField(typeExpr: 'decimal')]
    public string $total;
}

MaxiField supports the following options:

Option Type Description
typeExpr ?string MAXI type expression ('int', 'str[]', 'enum[a,b]', 'U')
annotation ?string Type annotation ('email', 'base64', 'hex')
required bool Adds the ! (required) constraint
id bool Marks this field as the record identifier
defaultValue mixed Default value when field is omitted
name ?string Override the serialized field name (defaults to property name)
constraints ?string Raw constraint string (e.g. '>=3,<=50')

Schema registry for third-party classes

For classes you don't own (no Attributes), register a schema descriptor manually:

use Maxi\Registry\MaxiSchemaRegistry;

MaxiSchemaRegistry::define(ThirdPartyUser::class, [
    'alias'  => 'U',
    'name'   => 'User',
    'fields' => [
        ['name' => 'id',    'typeExpr' => 'int', 'constraints' => [['type' => 'id']]],
        ['name' => 'name'],
        ['name' => 'email', 'annotation' => 'email'],
    ],
]);

Error handling

All parse/dump errors throw Maxi\Core\MaxiException which carries structured context:

use Maxi\Core\MaxiException;

try {
    Maxi::parse($input, ['allowTypeCoercion' => 'error']);
} catch (MaxiException $e) {
    echo $e->errorCode;    // e.g. 'E402'
    echo $e->maxiLine;     // line number where the error occurred
    echo $e->maxiFilename; // filename (if provided via options)
    echo $e->getMessage(); // human-readable description
}

Error codes

Code Name Description
E101 InvalidSyntaxError General syntax error
E102 DuplicateTypeError Duplicate type alias in schema
E103 UnknownDirectiveError Unrecognised @directive
E201 UnknownTypeError Record uses undefined type alias
E202 UndefinedParentError Parent type not defined
E203 CircularInheritanceError Circular type inheritance
E204 UnresolvedReferenceError Reference ID not found
E205 DuplicateIdentifierError Duplicate id in records
E301 ConstraintSyntaxError Malformed constraint
E302 InvalidConstraintValueError Invalid constraint value
E303 ConstraintViolationError Value violates a constraint
E304 ArraySyntaxError Malformed array literal
E401 SchemaMismatchError Too many/few values for type
E402 TypeMismatchError Value doesn't match field type
E403 MissingRequiredFieldError Required field is null/missing
E404 InvalidDefaultValueError Default value type mismatch
E405 UnsupportedBinaryFormatError Invalid bytes annotation
E501 EnumAliasError Duplicate or ambiguous enum alias
E601 UnsupportedVersionError @version value not supported
E602 SchemaLoadError Error loading external schema
E603 StreamError Error during streaming parse

Parser behavior options

By default, the parser warns on type mismatches, missing fields, and constraint violations instead of throwing. Tune this per option:

// Warn on type mismatches (default)
$result = Maxi::parse($input);

foreach ($result->warnings as $w) {
    echo "[{$w->code}] {$w->message} (line {$w->line})\n";
}

To make any of these fatal, set the relevant option to 'error':

// Throw on type mismatches
$result = Maxi::parse($input, ['allowTypeCoercion' => 'error']);

// Throw on any schema violation
$result = Maxi::parse($input, [
    'allowTypeCoercion'         => 'error',
    'allowMissingFields'        => 'error',
    'allowAdditionalFields'     => 'error',
    'allowConstraintViolations' => 'error',
]);

External schema imports

MAXI files can import type definitions from external .mxs schema files. Provide a loadSchema callback to resolve them:

$result = Maxi::parse($input, [
    'loadSchema' => function (string $path): string {
        return file_get_contents(__DIR__ . '/schemas/' . $path);
    },
]);

MAXI format (quick reference)

U:User(id:int|name|email=unknown)   ← type definition
###                                 ← section separator
U(1|Julie|~)                        ← record  (~ = explicit null)
  • Omitted trailing fields use their declared default value.
  • ~ sets a field to explicit null, even if it has a default.
  • Arrays: [1,2,3] — Maps: {key:value,key2:value2}
  • Inline objects: O(100|(1|Julie|julie@maxi.org)|99.99)
  • See the MAXI spec for the full format definition.

Test

composer test

License

Released under the MIT License.

统计信息

  • 总下载量: 3
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 10
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-05-06

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固