Protocol Buffers works great with PHP for building efficient web APIs and microservices. While JSON is common in PHP, Protobuf offers faster serialization and smaller payloads, especially useful for high-traffic applications or mobile API backends.
This guide walks you through everything you need to get started with Protocol Buffers in PHP, from installation to building real working examples. We'll keep it simple and practical.
What You'll Need
- •PHP: Version 7.4 or higher (check with
php -v
) - •Composer: PHP package manager (get it here)
- •Protocol Buffer Compiler: We'll install this in the next step
Step 1: Install Protocol Buffers
First, install the PHP protobuf extension using Composer:
composer require google/protobuf
Next, install the Protocol Buffer compiler (protoc
). On Ubuntu/Debian:
sudo apt update sudo apt install protobuf-compiler # Verify installation protoc --version
On macOS with Homebrew:
brew install protobuf
On Windows, download from the official releases page and add to your PATH.
Step 2: Set Up Your Project
Create a new PHP project:
mkdir php-protobuf-demo cd php-protobuf-demo composer init --name="your-name/protobuf-demo" composer require google/protobuf mkdir protos mkdir generated
This creates a basic PHP project with folders for your proto files and generated code.
Step 3: Create Your .proto File
Create a file called protos/subscriber.proto
. We'll use a telecom subscriber example:
syntax = "proto3"; package telecom; // Mobile subscriber information message Subscriber { string msisdn = 1; // Mobile number string name = 2; // Subscriber name string email = 3; // Email address SubscriptionType type = 4; // Plan type bool active = 5; // Account status repeated string services = 6; // Active services } enum SubscriptionType { PREPAID = 0; POSTPAID = 1; CORPORATE = 2; }
Note: In PHP, we use the package
declaration which will become the namespace in generated PHP code.
Step 4: Compile the .proto File
Generate PHP classes from your proto file:
protoc --php_out=generated --proto_path=protos protos/subscriber.proto
This creates PHP files in the generated/
folder. The structure will be:
generated/ └── Telecom/ ├── Subscriber.php └── SubscriptionType.php
Step 5: Use Protocol Buffers in PHP
Create a file called example.php
:
<?php require_once __DIR__ . '/vendor/autoload.php'; use Telecom\Subscriber; use Telecom\SubscriptionType; // Create a new subscriber $subscriber = new Subscriber(); $subscriber->setMsisdn('+91-9876543210'); $subscriber->setName('Telecom Customer'); $subscriber->setEmail('customer@telecom.com'); $subscriber->setType(SubscriptionType::POSTPAID); $subscriber->setActive(true); $subscriber->setServices(['Voice', 'Data', '4G LTE']); echo "Created subscriber: " . $subscriber->getName() . "\n"; echo "MSISDN: " . $subscriber->getMsisdn() . "\n"; echo "Type: " . SubscriptionType::name($subscriber->getType()) . "\n"; // Serialize to binary $binaryData = $subscriber->serializeToString(); echo "Serialized to " . strlen($binaryData) . " bytes\n\n"; // Deserialize from binary $newSubscriber = new Subscriber(); $newSubscriber->mergeFromString($binaryData); echo "Deserialized subscriber: " . $newSubscriber->getName() . "\n"; echo "Email: " . $newSubscriber->getEmail() . "\n"; echo "Active: " . ($newSubscriber->getActive() ? 'Yes' : 'No') . "\n"; // Access repeated fields (services) echo "\nActive services:\n"; foreach ($newSubscriber->getServices() as $service) { echo " - $service\n"; }
Step 6: Run Your Application
Run the PHP script:
php example.php
You should see output like:
Created subscriber: Telecom Customer MSISDN: +91-9876543210 Type: POSTPAID Serialized to 78 bytes Deserialized subscriber: Telecom Customer Email: customer@telecom.com Active: Yes Active services: - Voice - Data - 4G LTE
Saving and Loading from Files
Save and load protobuf data to/from files:
<?php require_once __DIR__ . '/vendor/autoload.php'; use Telecom\Subscriber; use Telecom\SubscriptionType; // Create subscriber $subscriber = new Subscriber(); $subscriber->setMsisdn('+91-9123456789'); $subscriber->setName('Network Admin'); $subscriber->setEmail('admin@telecom.com'); $subscriber->setType(SubscriptionType::CORPORATE); $subscriber->setActive(true); // Save to file file_put_contents('subscriber.bin', $subscriber->serializeToString()); echo "Saved to file\n"; // Load from file $loadedSubscriber = new Subscriber(); $loadedSubscriber->mergeFromString(file_get_contents('subscriber.bin')); echo "Loaded: " . $loadedSubscriber->getName() . "\n"; echo "MSISDN: " . $loadedSubscriber->getMsisdn() . "\n";
Convert Between JSON and Protobuf
PHP protobuf library supports JSON conversion:
<?php require_once __DIR__ . '/vendor/autoload.php'; use Telecom\Subscriber; use Telecom\SubscriptionType; use Google\Protobuf\Internal\Message; // Create subscriber $subscriber = new Subscriber(); $subscriber->setMsisdn('+91-9876543210'); $subscriber->setName('Mobile User'); $subscriber->setType(SubscriptionType::PREPAID); // Convert to JSON $jsonString = $subscriber->serializeToJsonString(); echo "JSON output:\n"; echo $jsonString . "\n\n"; // Parse from JSON $jsonData = '{ "msisdn": "+91-9111111111", "name": "New Subscriber", "type": "POSTPAID", "active": true }'; $newSubscriber = new Subscriber(); $newSubscriber->mergeFromJsonString($jsonData); echo "Parsed from JSON: " . $newSubscriber->getName() . "\n"; echo "Type: " . SubscriptionType::name($newSubscriber->getType()) . "\n";
Using Protobuf with Laravel
Here's how to use Protobuf in a Laravel API controller:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Http\Response; use Telecom\Subscriber; use Telecom\SubscriptionType; class SubscriberController extends Controller { public function create(Request $request) { // Accept JSON, convert to Protobuf $subscriber = new Subscriber(); $subscriber->setMsisdn($request->input('msisdn')); $subscriber->setName($request->input('name')); $subscriber->setEmail($request->input('email')); $subscriber->setType(SubscriptionType::POSTPAID); $subscriber->setActive(true); // Save to database or process... // Return protobuf binary return response($subscriber->serializeToString()) ->header('Content-Type', 'application/x-protobuf'); } public function get($msisdn) { // Fetch subscriber from database // For demo, create one $subscriber = new Subscriber(); $subscriber->setMsisdn($msisdn); $subscriber->setName('Retrieved Subscriber'); $subscriber->setType(SubscriptionType::PREPAID); // Return as protobuf return response($subscriber->serializeToString()) ->header('Content-Type', 'application/x-protobuf'); } public function parse(Request $request) { // Receive protobuf binary in request $subscriber = new Subscriber(); $subscriber->mergeFromString($request->getContent()); // Process the subscriber return response()->json([ 'name' => $subscriber->getName(), 'msisdn' => $subscriber->getMsisdn(), 'type' => SubscriptionType::name($subscriber->getType()) ]); } }
Best Practices for PHP
Use Composer Autoloading
Always use composer autoload
instead of manually requiring files. This ensures proper namespace loading.
Handle Binary Data Carefully
When sending protobuf over HTTP, set the correct content type:application/x-protobuf
Keep Generated Code Separate
Store generated PHP files in a separate directory and don't edit them manually. They'll be overwritten on recompilation.
Check Field Existence
Use has
methods to check if optional fields are set before accessing them.
Common Issues
Issue: Class not found after compilation
Solution: Make sure your generated files are in a directory that Composer can autoload. Update composer.json
to include the generated directory in the autoload section.
Issue: protoc command not found
Solution: Install the Protocol Buffer compiler using your system package manager or download from GitHub releases.
Issue: Namespace errors
Solution: PHP uses the package
name from your .proto file as the namespace. Make sure it follows PHP naming conventions.
Related Tools
Additional Resources
Official Documentation & References
- Official PHP Protobuf Tutorial - Google's official PHP guide
- PHP Protobuf on GitHub - Source code and examples
- Protobuf on Packagist - PHP package repository
Conclusion
Protocol Buffers integrates smoothly with PHP, especially for building efficient APIs and microservices. While JSON is more common in the PHP world, Protobuf shines when you need speed, smaller payloads, or are building mobile backends.
Start with the simple examples here, then integrate into your Laravel, Symfony, or custom PHP applications. The performance benefits become clear when handling high traffic or mobile clients with limited bandwidth.