centraldesktop/protobuf-php
PHP implementation of Google Protocol Buffers with a protoc plugin to generate type-hinted PHP classes from .proto files. Supports binary serialization, multiple codecs (JSON/XML/etc), services, extensions, reflection, and dynamic messages with lazy decoding.
Installation:
composer require centraldesktop/protobuf-php
Ensure protoc (v2.3+) is installed and in your PATH.
Generate PHP Classes:
protoc --plugin=protoc-gen-php --php_out=./generated tutorial.proto
For custom options (e.g., php.namespace), include the php.proto file:
protoc -I=./vendor/centraldesktop/protobuf-php/library/DrSlump/Protobuf/Compiler/protos \
--plugin=protoc-gen-php --php_out=./generated tutorial.proto
First Use Case:
use Generated\Tutorial\Person;
$person = new Person();
$person->name = 'John Doe';
$person->setId(42);
// Serialize to binary
$binaryData = $person->serialize();
// Deserialize
$decodedPerson = Person::parseFrom($binaryData);
Code Generation:
protoc plugin to generate PHP classes from .proto files.php.tpl) for advanced use cases (e.g., adding validation logic).php.tpl to inject custom setters/getters:
// In your custom template:
{foreach $fields}
public function setCustom{$field.name}({$field.type} $value) {
$this->set{$field.name}($value);
// Add custom logic here
}
{/foreach}
Serialization/Deserialization:
$data = $message->serialize(); // Binary
$decoded = Message::parseFrom($data);
$codec = new \DrSlump\Protobuf\Codec\Json();
$jsonData = $codec->encode($message);
$decoded = $codec->decode($jsonData, Message::class);
Dynamic Messages:
$dynamicMessage = new \DrSlump\Protobuf\DynamicMessage();
$dynamicMessage->setField('name', 'Dynamic Value');
$data = $dynamicMessage->serialize();
Lazy Decoding:
$message = Message::parseFrom($data);
$fieldValue = $message->getLazyField('field_name')->getValue(); // Decodes on access
int, string) in generated classes for IDE autocompletion and runtime validation.Tutorial\ServiceInterface).$mock = $this->getMockBuilder(Message::class)
->disableOriginalConstructor()
->onlyMethods(['getField'])
->getMock();
Integer Handling:
int32, int64, or fixed64 require GMP or BC Math extensions.
Fix: Enable extensions or use zigzag encoding (if supported by your .proto).PHP_INT_MAX (e.g., uint64) may lose precision.
Workaround: Use double or validate inputs.String Encoding:
$message->setName(mb_convert_encoding($name, 'UTF-8'));
Memory Usage:
Unknown Fields:
UnknownFieldSet for inspection:
$unknownFields = $message->getUnknownFields();
Breaking Changes:
Option return types for getters (e.g., getName() → Option<string>).
Fix: Update calls to handle Option objects:
if ($message->getName()->isPresent()) {
$name = $message->getName()->get();
}
.proto Files:
Use protoc --decode_raw to inspect binary data:
protoc --decode_raw --decode_raw_input=binary data.bin
file_put_contents('debug.bin', $message->serialize());
\DrSlump\Protobuf\Codec\CodecInterface for new formats (e.g., Avro):
class CustomCodec implements CodecInterface {
public function encode($message) { ... }
public function decode($data, $className) { ... }
}
php.tpl to modify generated classes (e.g., add timestamps):
// In your custom template:
{foreach $fields}
public $createdAt;
{/foreach}
@protobuf.annotation in .proto files to customize behavior:
message User {
optional string name = 1 [protobuf.annotation = "validate:min=3"];
}
Note: Requires custom template logic to process annotations.php.namespace in .proto to avoid collisions:
option php.namespace = "App\\Protobuf";
-Dmultifile=true to generate classes across multiple files:
protoc-gen-php -o ./generated -Dmultifile=true *.proto
How can I help you explore Laravel packages today?