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 ディレクトリを自動的に作成しますが、buildbuild/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 にはネイティブの enum がないため、代わりにプロトコルバッファコンパイラは、メッセージと同様に、.proto ファイル内の各 enum 型に対して PHP クラスを生成し、各値に対して定数を定義します。したがって、次の enum が与えられた場合:

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

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

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

メッセージと同様に、PHP はネストされたクラスをサポートしていないため、ネストされた enum は、それを含むメッセージ(複数可)をプレフィックスとし、アンダースコアで区切られた同じ名前の PHP クラスになります。

class TestMessage_NestedEnum {...}

enum クラスまたは値の名前が予約語(例:Empty)の場合、プレフィックス PB がクラスまたは値の名前の先頭に追加されます。

class PBEmpty {
  const PBECHO = 0;
}

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

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 内のフィールドを表す enum 値を返します。