Я получаю сообщение protobuf (синтаксис 2) с другого сервера в c ++ и с другого сервера в php, я получаю то же самое сообщение protobuf (синтаксис 3). Теперь моя цель — расшифровать это сообщение.
Ниже приведены файлы:
Файл .proto:
syntax="proto3";
message ModuleDescriptor {
string name = 1;
string identifier = 2;
string version = 3;
float frequency = 4;
}
message RuntimeStatistic {
double sliceConsumption = 1;
}
message ModuleStatistic {
ModuleDescriptor module = 1;
RuntimeStatistic runtimeStatistic = 2;
}
message ModuleStatistics {
repeated ModuleStatistic moduleStatistics = 1; //this is the message that i receive
}
Этот прото файл генерирует 4 класса. Вот класс ModuleStatistics:
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: ModuleStatistics.proto
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Protobuf type <code>ModuleStatistics</code>
*/
class ModuleStatistics extends \Google\Protobuf\Internal\Message
{
/**
* <code>repeated .ModuleStatistic moduleStatistics = 1;</code>
*/
private $moduleStatistics;
public function __construct() {
\GPBMetadata\ModuleStatistics::initOnce();
parent::__construct();
}
/**
* <code>repeated .ModuleStatistic moduleStatistics = 1;</code>
*/
public function getModuleStatistics()
{
return $this->moduleStatistics;
}
/**
* <code>repeated .ModuleStatistic moduleStatistics = 1;</code>
*/
public function setModuleStatistics(&$var)
{
$arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \ModuleStatistic::class);
$this->moduleStatistics = $arr;
}
}
файл index.php:
include_once './vendor/autoload.php';
require_once("generated_proto/GPBMetadata/ModuleStatistics.php");
require_once("generated_proto/ModuleDescriptor.php");
require_once("generated_proto/RuntimeStatistic.php");
require_once("generated_proto/ModuleStatistic.php");
require_once("generated_proto/ModuleStatistics.php");
...
$protoClass = new ModuleStatistics(); //MoudleStatitistics is a generated class from protobuff
$protoClass -> mergeFromString($receivedString); //decode the string received from the c++ server
echo $protoClass ->getModuleStatistics(); // getModuleStatisics() is a function in the generated class ModulseStatistics.
...
Это весь код, который у меня есть для буферов протокола.
Теперь, когда я пытаюсь проникнуть внутрь getModuleStatistics()
функция, она выдает мне эту ошибку: PHP Catchable fatal error: Object of class ModuleStatistics could not be converted to string in /app/index.php on line 41
mergeFromString()
не дает мне никакой ошибки, но и ничего не запускает.
Я получаю только 1 из 4 сообщений прото-файла. Но, как вы можете видеть, это вложенное сообщение. Нужно ли мне получать все 4 сообщения? И тогда, может быть, установить их друг к другу?
Глядя на ваш файл .proto, кажется, что фактические данные, к которым вы хотите получить, все еще вкладываются немного глубже …
Иерархия объектов для классов PHP, сгенерированных из вашего прототипа, выглядит примерно так:
ModuleStatistics
|
+---- ModuleStatistic
| |
| +---- ModuleDescriptor
| |
| +---- RuntimeStatistic
|
+---- ModuleStatistic
|
+---- ModuleDescriptor
|
+---- RuntimeStatistic
Так сказать ModuleStatistics
является итерируемый объект возможно содержащий несколько отдельных ModuleStatistic
объекты — ноль или более.
каждый ModuleStatistic
объект содержит еще два объекта —
ModuleDescriptor
а также RuntimeStatistic
, которые являются объектами значений, содержащими фактические данные, которые вы предположительно хотите распечатать или иным образом использовать в своей программе.
Эти объекты содержат геттеры для своих данных, и я рекомендую вам прочитать сгенерированные классы PHP, чтобы ознакомиться с конкретными интерфейсами, которые для них создаются.
Таким образом, вы должны быть в состоянии сделать что-то вроде этого, чтобы отобразить отдельные значения:
// First, let's grab the return value from `getModuleStatistics()`
// which is a `ModuleStatistics` object
$moduleStatistics = $protoClass->getModuleStatistics();
// `ModuleStatistics` is an object that implements PHP's
// `Iterator` interface, meaning you can iterate over it
// with `foreach`. It will return zero or more nested
// `ModuleStatistic` objects
foreach ($moduleStatistics as $moduleStatistic) {
// Each `ModuleStatistic` itself contains two more nested
// objects: `RuntimeStatistic` and `ModuleDescriptor`
$runtimeStatistic = $moduleStatistic->getRuntimeStatistic();
$moduleDescriptor = $moduleStatistic->getModule();
// these nested objects contain the actual
// scalar values that you can echo
echo $runtimeStatistic->getSliceConsumption(); // returns a double
echo $moduleDescriptor->getName(); // returns a string
echo $moduleDescriptor->getIdentifier(); // returns a string
echo $moduleDescriptor->getVersion(); // returns a string
echo $moduleDescriptor->getFrequency(); // returns a double
}
Я, очевидно, не проверял этот код, потому что у меня нет ваших данных, так что YMMV. Если вы сомневаетесь в возвращаемых значениях методов, прочитайте сгенерированный код или используйте var_dump()
или же print_r()
проверить содержимое переменной.
Надеюсь это поможет.
Что касается следующей ошибки:
Неисправимая PHP-фатальная ошибка: объект класса ModuleStatistics не может быть преобразован в строку в /app/index.php в строке 41
Линия echo $protoClass ->getModuleStatistics();
возвращает экземпляр класса ModuleStatistics
который вы затем пытаетесь echo
,
Это не может быть сделано, потому что ModuleStatistics
не имеет __toString()
метод. Так что либо не пытайтесь echo
объект, или добавить __toString()
Способ; например:
<?php
class ModuleStatistics
{
// etc.
public function __toString()
{
// `return` the desired string representation of your object here
}
}
Ссылка:
Других решений пока нет …