Skip to content
Shuhei Tanuma edited this page Dec 31, 2013 · 14 revisions

Basics

please check google's document at first.

https://developers.google.com/protocol-buffers/docs/overview

building php-protocolbuffers

linux like system

git clone https://github.com/chobie/php-protocolbuffers.git
cd php-protocolbuffers
phpize
./configure
make
make install
# please add following line to your php.ini
# extension=protocolbuffers.so

windows

git clone https://github.com/chobie/php-protocolbuffers.git
cd php-protocolbuffers
phpize
configure --with-protocolbuffers
nmake
# copy Release_TS\php_protocolbuffers.dll into your php directory
# don't forget to add following line to your php.ini
# extension=php_protocolbuffers.dll

setup protoc-gen-php

You need install protoc-gen-php when generating message from .proto file.

git clone https://github.com/chobie/protoc-gen-php.git
composer install

create your first message

NOTE: please use improved-protoc-gen-php at this time.

puts below contents into person.proto.

package chobie;

message Person
{
  required int32 user_id = 1;
  optional string name = 2;
}

okay, let's generate php classes with protoc

$ mkdir php
$ protoc --plugin=protoc-gen-php --php_out=php person.proto

then you can see below files.

 /usr/local/bin/tree php
php
├── autoload.php     # example autoloader implementation
├── chobie
│   └── Person.php   # chobie\Person class
└── person.proto.php # `require` this file.

1 directory, 3 files

when you want to use chobie\Person class, you just do require person.proto.php or setup PSR-4 style autoloader.

<?php
require "path/to/person.proto.php";

$person = new chobie\Person();
$person->setUserId(1234);
$person->setName("chobie");

$raw = $person->serializeToString();
$person2 = chobie\Person::parseFromString($raw);

var_dump($person2);
printf("raw protocol buffers message size: %d\n", strlen($raw));
printf("php serialize message size: %d\n", strlen(serialize($raw)));

this will output:

object(chobie\Person)#3 (2) {
  ["user_id":protected]=>
  string(4) "1234"
  ["name":protected]=>
  string(6) "chobie"
}
raw protocol buffers message size: 11
php serialize message size: 19

See, it's very easy. In most cases, protocolbuffers reduces serialized message bytes. this means:

  • you can reduce memory
  • you can reduce serialize/deserialize time.
  • really portable, small format. and also keep easy to use application.

generated class (example)

<?php
namespace chobie;

// @@protoc_insertion_point(namespace:.chobie.Person)

/**
 * Generated by the protocol buffer compiler.  DO NOT EDIT!
 * source: p2.proto
 *
 * -*- magic methods -*-
 *
 * @method string getUserId()
 * @method void setUserId(string $value)
 * @method string getName()
 * @method void setName(string $value)
 */
class Person extends \ProtocolBuffers\Message
{
  // @@protoc_insertion_point(traits:.chobie.Person)
  
  /**
   * @var string $user_id
   * @tag 1
   * @label required
   * @type \ProtocolBuffers::TYPE_INT32
   **/
  protected $user_id;
  
  /**
   * @var string $name
   * @tag 2
   * @label optional
   * @type \ProtocolBuffers::TYPE_STRING
   **/
  protected $name;
  
  
  // @@protoc_insertion_point(properties_scope:.chobie.Person)

  // @@protoc_insertion_point(class_scope:.chobie.Person)

  /**
   * get descriptor for protocol buffers
   * 
   * @return \ProtocolBuffersDescriptor
   */
  public static function getDescriptor()
  {
    static $descriptor;
    
    if (!isset($descriptor)) {
      $desc = new \ProtocolBuffers\DescriptorBuilder();
      $desc->addField(1, new \ProtocolBuffers\FieldDescriptor(array(
        "type"     => \ProtocolBuffers::TYPE_INT32,
        "name"     => "user_id",
        "required" => true,
        "optional" => false,
        "repeated" => false,
        "packable" => false,
        "default"  => null,
      )));
      $desc->addField(2, new \ProtocolBuffers\FieldDescriptor(array(
        "type"     => \ProtocolBuffers::TYPE_STRING,
        "name"     => "name",
        "required" => false,
        "optional" => true,
        "repeated" => false,
        "packable" => false,
        "default"  => "",
      )));
      // @@protoc_insertion_point(builder_scope:.chobie.Person)

      $descriptor = $desc->build();
    }
    return $descriptor;
  }

}