Расшифровка сообщения в буферах протокола php

Я получаю сообщение 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 сообщения? А потом, может быть, установить их друг на друга?


person Fisnik Hajredini    schedule 05.08.2017    source источник


Ответы (1)


Обновлять

Глядя на ваш файл .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 Catchable: объект класса 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
    }
}

Ссылка:

person Darragh Enright    schedule 06.08.2017
comment
Я попытался повторить это, потому что не знаю, как это сделать. Я добавил сгенерированный файл в вопрос. Он говорит в файле не редактировать его, если я все еще добавляю эту функцию. И если я добавлю его, какую строку я верну? - person Fisnik Hajredini; 06.08.2017
comment
@FisnikHajredini - Это автоматически сгенерированный класс? Тогда нет - не создавайте __toString() метод, потому что он будет перезаписан. - person Darragh Enright; 06.08.2017
comment
Что касается Message::mergeFromString() - вы правы, он ничего не возвращает - это задумано: github.com/google/protobuf/blob/master/php/src/Google/Protobuf/ - person Darragh Enright; 06.08.2017
comment
Итак, вопрос в том, что мы знаем, что вы не можете echo класс, не предоставив __toString() реализацию, и мы знаем, что мы не можем этого сделать в этом случае, потому что ModuleStatistics является автоматически сгенерированным классом. Итак, главный вопрос - что вы хотите делать с этим объектом? - person Darragh Enright; 06.08.2017
comment
Это сообщение содержит строку с информацией. Я буду получать сообщение каждую секунду, и мне нужно его отобразить. Это означает, что мне нужно декодировать его в строку. Есть ли способ сделать это? зачем вам этот объект, если вы не можете декодировать его в удобочитаемую строку. - person Fisnik Hajredini; 06.08.2017
comment
мой ModuleStatistics.php был неправильным, я случайно добавил ModuleStatistic.php (без s). Исправлено сейчас. getModuleStatistics не возвращает класс ModuleStatistic, он возвращает класс ModuleStatistics - person Fisnik Hajredini; 08.08.2017
comment
Большой. Если вы считаете, что мой ответ или комментарии помогли вам, не стесняйтесь проголосовать за вопрос или пометить вопрос как ответ. - person Darragh Enright; 09.08.2017