PHP 生成コード ガイド

特定のプロトコル定義のためにプロトコル バッファ コンパイラが生成する PHP コードについて説明します。

このドキュメントを読む前に、proto3 言語ガイドを読むことをお勧めします。プロトコル バッファ コンパイラは現在、PHP 用の proto3 コード生成のみをサポートしていることに注意してください。

コンパイラの呼び出し

プロトコル バッファ コンパイラは、`--php_out=` コマンドライン フラグを指定して呼び出されると、PHP 出力を生成します。`--php_out=` オプションのパラメータは、コンパイラが PHP 出力を書き込むディレクトリです。PSR-4 に準拠するため、コンパイラは proto ファイルで定義されたパッケージに対応するサブディレクトリを作成します。さらに、proto ファイル入力内の各メッセージに対して、コンパイラはパッケージのサブディレクトリに個別のファイルを作成します。メッセージの出力ファイル名は、次の3つの部分で構成されます。

  • ベースディレクトリ: proto パス (`--proto_path=` または `-I` コマンドライン フラグで指定) は、出力パス (`--php_out=` フラグで指定) に置き換えられます。
  • サブディレクトリ: パッケージ名内の `.` は、オペレーティングシステムのディレクトリ区切り文字に置き換えられます。各パッケージ名コンポーネントは大文字になります。
  • ファイル: メッセージ名に `.php` が追加されます。

例えば、次のようにコンパイラを呼び出したとします。

protoc --proto_path=src --php_out=build/gen src/example.proto

そして `src/example.proto` が次のように定義されている場合

package foo.bar;
message MyMessage {}

コンパイラは `src/foo.proto` ファイルを読み込み、出力ファイル `build/gen/Foo/Bar/MyMessage.php` を生成します。必要であれば、コンパイラはディレクトリ `build/gen/Foo/Bar` を自動的に作成しますが、`build` や `build/gen` は*作成しません*。これらは既に存在している必要があります。

パッケージ

`.proto` ファイルで定義されたパッケージ名は、デフォルトで生成された PHP クラスのモジュール構造を生成するために使用されます。次のようなファイルの場合、

package foo.bar;

message MyMessage {}

プロトコル コンパイラは、`Foo\Bar\MyMessage` という名前の出力クラスを生成します。

名前空間オプション

コンパイラは、PHP およびメタデータ名前空間を定義するための追加オプションをサポートしています。これらが定義されている場合、これらはモジュール構造と名前空間を生成するために使用されます。次のようなオプションの場合、

package foo.bar;
option php_namespace = "baz\\qux";
option php_metadata_namespace = "Foo";
message MyMessage {}

プロトコル コンパイラは、`baz\qux\MyMessage` という名前の出力クラスを生成します。このクラスには `namespace baz\qux` という名前空間が設定されます。

プロトコル コンパイラは、`Foo\Metadata` という名前のメタデータクラスを生成します。このクラスには `namespace Foo` という名前空間が設定されます。

生成されるオプションは、大文字と小文字を区別します。デフォルトでは、パッケージはパスカルケースに変換されます。

メッセージ

単純なメッセージ宣言の場合

message Foo {}

プロトコル バッファ コンパイラは、`Foo` という PHP クラスを生成します。このクラスは、`Google\Protobuf\Internal\Message` という共通の基底クラスを継承しており、以下の例に示すように、メッセージ型のエンコードおよびデコードのためのメソッドを提供します。

$from = new Foo();
$from->setInt32(1);
$from->setString('a');
$from->getRepeatedInt32()[] = 1;
$from->getMapInt32Int32()[1] = 1;
$data = $from->serializeToString();
try {
  $to->mergeFromString($data);
} catch (Exception $e) {
  // Handle parsing error from invalid data.
  ...
}

独自の `Foo` サブクラスを*作成しないでください*。生成されたクラスはサブクラス化のために設計されておらず、「壊れやすい基底クラス」の問題につながる可能性があります。

ネストされたメッセージは、PHP がネストされたクラスをサポートしていないため、内包するメッセージをプレフィックスとしてアンダースコアで区切られた同じ名前の PHP クラスになります。例えば、`.proto` に次のように記述されている場合、

message TestMessage {
  optional int32 a = 1;
  message NestedMessage {...}
}

コンパイラは次のクラスを生成します

class TestMessage {
  public a;
}

// PHP doesn’t support nested classes.
class TestMessage_NestedMessage {...}

メッセージクラス名が予約されている場合 (例えば `Empty`)、クラス名の前に `PB` というプレフィックスが付加されます。

class PBEmpty {...}

また、ファイルレベルのオプション `php_class_prefix` も提供しています。これが指定されている場合、生成されるすべてのメッセージクラスの前に付加されます。

フィールド

メッセージ型内の各フィールドには、そのフィールドを設定および取得するためのアクセサメソッドがあります。したがって、フィールド `x` が与えられた場合、次のように記述できます。

$m = new MyMessage();
$m->setX(1);
$val = $m->getX();

$a = 1;
$m->setX($a);

フィールドを設定するたびに、値はそのフィールドの宣言された型に対して型チェックされます。値が誤った型である場合 (または範囲外である場合)、例外がスローされます。デフォルトでは、型変換 (例えば、フィールドに値を割り当てる場合や繰り返しフィールドに要素を追加する場合) は、整数、浮動小数点数、数値文字列との間で許可されます。許可されない変換には、配列またはオブジェクトとの間のすべての変換が含まれます。浮動小数点数から整数へのオーバーフロー変換は未定義です。

各スカラ プロトコル バッファ型に対応する PHP 型は、スカラ値型テーブルで確認できます。

単一メッセージフィールド

メッセージ型のフィールドはデフォルトで nil になり、フィールドがアクセスされても自動的には作成されません。したがって、次のようにサブメッセージを明示的に作成する必要があります。

$m = new MyMessage();
$m->setZ(new SubMessage());
$m->getZ()->setFoo(42);

$m2 = new MyMessage();
$m2->getZ()->setFoo(42);  // FAILS with an exception

インスタンスが他の場所 (例えば、別のメッセージのフィールド値として) でも保持されている場合でも、任意のインスタンスをメッセージフィールドに割り当てることができます。

繰り返しフィールド

プロトコル バッファ コンパイラは、各繰り返しフィールドに対して特殊な `RepeatedField` を生成します。例えば、次のフィールドが与えられた場合、

repeated int32 foo = 1;

生成されたコードでは、次のように実行できます。

$m->getFoo()[] =1;
$m->setFoo($array);

マップフィールド

プロトコル バッファ コンパイラは、各マップフィールドに対して `MapField` を生成します。したがって、このフィールドが与えられた場合、

map<int32, int32> weight = 1;

生成されたコードで次の操作を実行できます。

$m->getWeight()[1] = 1;

列挙型

PHP にはネイティブな列挙型がないため、代わりにプロトコル バッファ コンパイラは、メッセージと同様に、`.proto` ファイル内の各列挙型に対して PHP クラスを生成し、各値には定数が定義されます。したがって、この列挙型が与えられた場合、

enum TestEnum {
  Default = 0;
  A = 1;
}

コンパイラは次のクラスを生成します

class TestEnum {
  const DEFAULT = 0;
  const A = 1;
}

メッセージと同様に、ネストされた列挙型も、PHP がネストされたクラスをサポートしていないため、内包するメッセージをプレフィックスとしてアンダースコアで区切られた同じ名前の PHP クラスになります。

class TestMessage_NestedEnum {...}

列挙型クラスまたは値の名前が予約されている場合 (例えば `Empty`)、クラスまたは値の名前の前に `PB` というプレフィックスが付加されます。

class PBEmpty {
  const PBECHO = 0;
}

また、ファイルレベルのオプション `php_class_prefix` も提供しています。これが指定されている場合、生成されるすべての列挙型クラスの前に付加されます。

Oneof

oneofの場合、プロトコル バッファ コンパイラは通常の単一フィールドと同じコードを生成しますが、どの oneof フィールド (もしあれば) が設定されているかを調べることができる特別なアクセサメソッドも追加します。したがって、このメッセージが与えられた場合、

message TestMessage {
  oneof test_oneof {
    int32 oneof_int32 = 1;
    int64 oneof_int64 = 2;
  }
}

コンパイラは次のフィールドと特別なメソッドを生成します

class TestMessage {
  private oneof_int32;
  private oneof_int64;
  public function getOneofInt32();
  public function setOneofInt32($var);
  public function getOneofInt64();
  public function setOneofInt64($var);
  public function getTestOneof();  // Return field name
}

アクセサメソッドの名前は oneof の名前に基づいており、現在設定されている oneof 内のフィールドを表す列挙値を返します。