PHPackages                             butschster/proto-parser - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. butschster/proto-parser

ActiveLibrary[Parsing &amp; Serialization](/categories/parsing)

butschster/proto-parser
=======================

Proto parser is a library for parsing Protocol Buffers files into AST

1.1.1(1y ago)58990↓50%3[5 issues](https://github.com/butschster/proto-parser/issues)MITPHPPHP &gt;=8.3CI passing

Since Aug 16Pushed 9mo ago1 watchersCompare

[ Source](https://github.com/butschster/proto-parser)[ Packagist](https://packagist.org/packages/butschster/proto-parser)[ RSS](/packages/butschster-proto-parser/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (5)Versions (11)Used By (0)

PHP Protocol Buffer Parser
==========================

[](#php-protocol-buffer-parser)

A powerful and flexible Protocol Buffers parser for PHP, capable of generating an Abstract Syntax Tree (AST) from `.proto` files. This package provides a robust foundation for working with Protocol Buffers in PHP projects.

Key Features
------------

[](#key-features)

- Full support for Protocol Buffer syntax (proto3)
- Parses messages, enums, services, and RPC definitions
- Handles imports, packages, and options
- Preserves comments for documentation purposes
- Generates an Abstract Syntax Tree (AST) for easy manipulation
- Built with PHP 8.3

Use Cases
---------

[](#use-cases)

- Generating code from protobuf definitions
- Analyzing and validating protobuf schemas
- Building tools for working with protocol buffers
- Integrating protobuf support into existing PHP applications

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require butschster/proto-parser
```

Usage
-----

[](#usage)

Here's a quick example of how to use the Proto Parser:

```
use Butschster\ProtoParser\ProtoParserFactory;

$parser = ProtoParserFactory::create();

$ast = $parser->parse(topLevelDefs[0]->name; // Outputs: Person
```

Understanding AST (Abstract Syntax Tree)
----------------------------------------

[](#understanding-ast-abstract-syntax-tree)

An Abstract Syntax Tree (AST) is a tree representation of the abstract syntactic structure of source code. In the context of this package, the AST represents the structure of a Protocol Buffer definition file.

Here's an example of what an AST looks like for a simple `.proto` file:

```
syntax = "proto3";

package example;

message Person {
    string name = 1;
    int32 id = 2;
    string email = 3;
}
```

The corresponding AST would look something like this:

```
ProtoNode
├── SyntaxDeclNode (syntax: "proto3")
├── PackageDeclNode (name: "example")
└── MessageDefNode (name: "Person")
    ├── FieldDeclNode (name: "name", type: "string", number: 1)
    ├── FieldDeclNode (name: "id", type: "int32", number: 2)
    └── FieldDeclNode (name: "email", type: "string", number: 3)

```

Each node in the AST corresponds to a specific element in the Protocol Buffer definition. This structure allows for easy traversal and manipulation of the Protocol Buffer structure programmatically.

AST Class Diagram
-----------------

[](#ast-class-diagram)

The following class diagram provides an overview of the AST node classes available in the Protobuf parser. This diagram shows the relationships between different node classes and their properties.

 ```
classDiagram
    ProtoNode *-- SyntaxDeclNode
    ProtoNode *-- "0..*" ImportDeclNode
    ProtoNode *-- "0..1" PackageDeclNode
    ProtoNode *-- "0..*" OptionDeclNode
    ProtoNode *-- "0..*" MessageDefNode
    ProtoNode *-- "0..*" EnumDefNode
    ProtoNode *-- "0..*" ServiceDefNode

    MessageDefNode *-- "0..*" FieldDeclNode
    MessageDefNode *-- "0..*" ReservedNode
    MessageDefNode *-- "0..*" MessageDefNode
    MessageDefNode *-- "0..*" EnumDefNode
    MessageDefNode *-- "0..*" CommentNode

    EnumDefNode *-- "0..*" EnumFieldNode
    EnumDefNode *-- "0..*" CommentNode

    ServiceDefNode *-- "0..*" RpcDeclNode
    ServiceDefNode *-- "0..*" OptionDeclNode
    ServiceDefNode *-- "0..*" CommentNode

    FieldDeclNode *-- FieldType
    FieldDeclNode *-- "0..1" FieldModifier
    FieldDeclNode *-- "0..*" OptionDeclNode
    FieldDeclNode *-- "0..*" CommentNode

    EnumFieldNode *-- "0..*" OptionDeclNode
    EnumFieldNode *-- "0..*" CommentNode

    RpcDeclNode *-- RpcMessageType
    RpcDeclNode *-- "0..*" OptionDeclNode
    RpcDeclNode *-- "0..*" CommentNode

    OptionDeclNode *-- "0..*" OptionNode
    OptionDeclNode *-- "0..*" CommentNode

    class ProtoNode {
        +SyntaxDeclNode syntax
        +ImportDeclNode[] imports
        +PackageDeclNode? package
        +OptionDeclNode[] options
        +MessageDefNode[] messages
        +EnumDefNode[] enums
        +ServiceDefNode[] services
    }

    class MessageDefNode {
        +string name
        +FieldDeclNode[] fields
        +ReservedNode[] reserved
        +MessageDefNode[] nestedMessages
        +EnumDefNode[] nestedEnums
        +CommentNode[] comments
    }

    class EnumDefNode {
        +string name
        +EnumFieldNode[] fields
        +CommentNode[] comments
    }

    class ServiceDefNode {
        +string name
        +RpcDeclNode[] methods
        +OptionDeclNode[] options
        +CommentNode[] comments
    }

    class FieldDeclNode {
        +FieldType type
        +string name
        +int number
        +FieldModifier? modifier
        +OptionDeclNode[] options
        +CommentNode[] comments
    }

    class EnumFieldNode {
        +string name
        +int number
        +OptionDeclNode[] options
        +CommentNode[] comments
    }

    class RpcDeclNode {
        +string name
        +RpcMessageType inputType
        +RpcMessageType outputType
        +OptionDeclNode[] options
        +CommentNode[] comments
    }

    class SyntaxDeclNode {
        +string syntax
        +CommentNode[] comments
    }

    class ImportDeclNode {
        +string path
        +ImportModifier? modifier
        +CommentNode[] comments
    }

    class PackageDeclNode {
        +string name
        +CommentNode[] comments
    }

    class OptionDeclNode {
        +string? name
        +OptionNode[] options
        +CommentNode[] comments
    }

    class CommentNode {
        +string text
    }

    class FieldType {
        +string type
    }

    class RpcMessageType {
        +string name
        +bool isStream
    }

    class OptionNode {
        +string name
        +mixed value
        +CommentNode[] comments
    }

    class ReservedNode {
        +ReservedRange[]|ReservedNumber[] ranges
        +CommentNode[] comments
    }
```

      Loading Detailed Usage Examples
-----------------------

[](#detailed-usage-examples)

### Parsing Messages

[](#parsing-messages)

```
$ast = $parser->parse(fields as $field) {
    echo "{$field->name}: {$field->type->type}\n";
}

$phoneTypeEnum = $personMessage->enums[0];
echo $phoneTypeEnum->name; // Outputs: PhoneType

$phoneNumberMessage = $personMessage->messages[0];
echo $phoneNumberMessage->name; // Outputs: PhoneNumber
```

### Parsing Services

[](#parsing-services)

```
$ast = $parser->parse(methods as $method) {
    echo "{$method->name}: {$method->inputType->name} -> {$method->outputType->name}\n";
}
```

### Handling Imports and Options

[](#handling-imports-and-options)

```
$ast = $parser->parse(options as $option) {
    echo "Option: {$option->name} = {$option->options[0]->value}\n";
}
```

Example: Generating DTO Classes
-------------------------------

[](#example-generating-dto-classes)

One powerful use case for the AST is generating Data Transfer Object (DTO) classes from Protocol Buffer definitions. You can use a code generator (like `nette/php-generator`) to create PHP classes based on the AST.

Here's an example of how you might use the AST to generate a PHP class:

```
use Butschster\ProtoParser\ProtoParser;
use Butschster\ProtoParser\ProtoParserFactory;
use Nette\PhpGenerator\ClassType;
use Nette\PhpGenerator\PhpFile;

$parser = ProtoParserFactory::create();
$ast = $parser->parse(addClass('Person');
$class->setFinal()
    ->setReadOnly();

foreach ($ast->topLevelDefs[0]->fields as $field) {
    $type = match ($field->type->type) {
        'string' => 'string',
        'int32' => 'int',
        default => 'mixed',
    };

    $property = $class->addProperty($field->name)
        ->setType($type)
        ->setPublic();

    if ($field->modifier === \Butschster\ProtoParser\Ast\FieldModifier::Repeated) {
        $property->setType('array');
    }
}

echo $file;
```

This would generate a PHP class like this:

```
