【问题标题】:Creating a Transaction Filter in PHP for creating a GetTransactionsRequest object在 PHP 中创建事务过滤器以创建 GetTransactionsRequest 对象
【发布时间】:2019-03-07 22:33:48
【问题描述】:

我正在编写一个向 DA Ledger 发出请求的客户端。我正在遵循我在之前的帖子 Doing CRUD on the DA Ledger through a gRPC client 中收到的建议。
我需要运行“GetTransactions”rpc。这样做需要 GetTransactionsRequest 对象。 GetTransactionsRequest 对象有一个名为“filter”的必需属性,它的类型为 TransactionFilter。我无法创建满足我需求的事务过滤器。它的 .proto 文件是:

// Used for filtering Transaction and Active Contract Set streams.
// Determines which on-ledger events will be served to the client.

message TransactionFilter {

  // Keys of the map determine which parties' on-ledger transactions are being queried.
  // Values of the map determine which events are disclosed in the stream per party.
  // At the minimum, a party needs to set an empty Filters message to receive any events.
  // Required
  map<string, Filters> filters_by_party = 1;
}

“filters_by_party”的唯一字段是必需的。 在php中设置该字段需要如下函数:

/**
     * Keys of the map determine which parties' on-ledger transactions are being queried.
     * Values of the map determine which events are disclosed in the stream per party.
     * At the minimum, a party needs to set an empty Filters message to receive any events.
     * Required
     *
     * Generated from protobuf field <code>map<string, .com.digitalasset.ledger.api.v1.Filters> filters_by_party = 1;</code>
     * @param array|\Google\Protobuf\Internal\MapField $var
     * @return $this
     */
    public function setFiltersByParty($var)
    {
        $arr = GPBUtil::checkMapField($var, \Google\Protobuf\Internal\GPBType::STRING, \Google\Protobuf\Internal\GPBType::MESSAGE, \Com\Digitalasset\Ledger\Api\V1\Filters::class);
        $this->filters_by_party = $arr;

        return $this;
    }

在 mapFiled 对象中设置值的 php 函数是:

/**
     * Assign the element at the given key.
     *
     * This will also be called for: $arr[$key] = $value
     *
     * @param object $key The key of the element to be fetched.
     * @param object $value The element to be assigned.
     * @return void
     * @throws ErrorException Invalid type for key.
     * @throws ErrorException Invalid type for value.
     * @throws ErrorException Non-existing key.
     */
    public function offsetSet($key, $value)
    {
        $this->checkKey($this->key_type, $key);

        switch ($this->value_type) {
            case GPBType::SFIXED32:
            case GPBType::SINT32:
            case GPBType::INT32:
            case GPBType::ENUM:
                GPBUtil::checkInt32($value);
                break;
            case GPBType::FIXED32:
            case GPBType::UINT32:
                GPBUtil::checkUint32($value);
                break;
            case GPBType::SFIXED64:
            case GPBType::SINT64:
            case GPBType::INT64:
                GPBUtil::checkInt64($value);
                break;
            case GPBType::FIXED64:
            case GPBType::UINT64:
                GPBUtil::checkUint64($value);
                break;
            case GPBType::FLOAT:
                GPBUtil::checkFloat($value);
                break;
            case GPBType::DOUBLE:
                GPBUtil::checkDouble($value);
                break;
            case GPBType::BOOL:
                GPBUtil::checkBool($value);
                break;
            case GPBType::STRING:
                GPBUtil::checkString($value, true);
                break;
            case GPBType::MESSAGE:
                if (is_null($value)) {
                  trigger_error("Map element cannot be null.", E_USER_ERROR);
                }
                GPBUtil::checkMessage($value, $this->klass);
                break;
            default:
                break;
        }

        $this->container[$key] = $value;
    }

例如,我如何将当事方名称“dealer1”和“dealer2”设置为过滤器_by_party 的当事方。我尝试了以下代码:

$parties= new Google\Protobuf\Internal\MapField(Google\Protobuf\Internal\GPBType::STRING,Google\Protobuf\Internal\GPBType::MESSAGE); 
$parties->offsetSet(0,"dealer1"); 
$parties->offsetSet(1,"dealer2"); 

导致以下错误:

PHP Fatal error:  Given value is not message. in /home/vantage/damlprojects/loaner_car/php/ledger_client.php on line 85

我不明白为什么是“消息” filter_by_party 'set' 函数需要。我不知道如何以“消息”的形式写经销商名称。似乎做一些应该很简单的事情却很复杂。将输入 $var 设置为“setFiltersByParty”函数的正确方法是什么?

【问题讨论】:

    标签: php grpc daml


    【解决方案1】:

    也许你可以在这里找到一些信息: https://developers.google.com/protocol-buffers/docs/reference/php-generated#fields

    对于地图字段,我猜应该是这样的:

    $m->getFiltersByParty()["string"] = new Filters();
    

    【讨论】:

    • 我需要按方设置过滤器,而不是按方获取过滤器。为了设置它们,我不需要调用函数 setFiltersByParty()。如果是这样,我需要创建一个新的 MapField 对象,设置它的参数,然后将其传递给 setFiltersByParty()。我没有看到任何关于如何设置 MapField 字段的在线文档。
    【解决方案2】:

    设置'dealer1'和dealer2'的代码如下:

    $parties= new Google\Protobuf\Internal\MapField(Google\Protobuf\Internal\GPBType::STRING,
       Google\Protobuf\Internal\GPBType::MESSAGE, "Com\Digitalasset\Ledger\Api\V1\Filters");
    
    $partyIdentifier = new Com\Digitalasset\Ledger\Api\V1\Identifier();
    $partyIdentifier->setPackageId($the_package_id); //last one from ListPackages()
    $partyIdentifier->setEntityName("<Module>");  //from DAML code
    $partyIdentifier->setModuleName("<Template>"); //from DAML code
    
    
    $partyInclusiveFilters = new Com\Digitalasset\Ledger\Api\V1\InclusiveFilters();
    $partyInclusiveFilters->setTemplateIds(array($partyIdentifier));
    
    $partyFilters = new Com\Digitalasset\Ledger\Api\V1\Filters();
    $partyFilters->setInclusive($partyInclusiveFilters);
    
    $parties->offsetSet("dealer1",$partyFilters);
    $parties->offsetSet("dealer2",$partyFilters);
    

    将 MapField 构造函数的第三个参数设置为“Com\Digitalasset\Ledger\Api\V1\Filters”很重要。正如 protobuf 文件所示:

    message TransactionFilter {
    
              // Keys of the map determine which parties' on-ledger transactions are being queried.
              // Values of the map determine which events are disclosed in the stream per party.
              // At the minimum, a party needs to set an empty Filters message to receive any events.
              // Required
              map<string, Filters> filters_by_party = 1;
            }
    

    filters_by_party 是具有“过滤器”的 value_type 的 MapField。 “过滤器”是一种消息类型(请参阅您的 transaction_filter.proto 文件),因此 MapField 构造函数需要知道它是什么类型的消息。

    经销商名称不是以“消息”的形式写入的,而是“filters_by_party”映射字段中对应于“过滤器”对象的键值。 “过滤器”是一种消息。我猜“简单”是一个相对术语。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-22
      • 2016-05-31
      • 1970-01-01
      • 2018-09-30
      • 2017-07-29
      相关资源
      最近更新 更多