代码之家  ›  专栏  ›  技术社区  ›  gsposato

从PHP向Firestore发布ArrayValue不起作用

  •  0
  • gsposato  · 技术社区  · 6 年前

    我正在从事一个使用Google Firestore版本1 beta 1的项目。 但是,没有为其提供PHP SDK,因此我必须使用REST API。

    我在网上找到了这本指南,它准确地解释了如何做到这一点: https://engineering.flosports.tv/google-cloud-firestore-document-crud-with-php-1df1c084e45b

    在阅读了指南之后,我能够得出结论,这个示例正如我所期望的那样工作。 但是,我需要使用ArrayValue,当我尝试使用ArrayValue时,会出现以下错误:

    string(612) "{
        "error": {
            "code": 400,
            "message": "Invalid JSON payload received. Unknown name \"array_value\" at 'document.fields[1].value': Proto field is not repeating, cannot start list.",
            "status": "INVALID_ARGUMENT",
            "details": [
              {
                "@type": "type.googleapis.com/google.rpc.BadRequest",
                "fieldViolations": [
                  {
                    "field": "document.fields[1].value",
                    "description": "Invalid JSON payload received. Unknown name \"array_value\" at 'document.fields[1].value': Proto field is not repeating, cannot start list."
                  }
                ]
              }
            ]
          }
        }
    "
    

    我从命令行运行示例文件,如下所示:

    php index.php
    

    这是索引。php

    <?php
    include("firestore.php");
    use PHPFireStore\FireStoreApiClient;
    use PHPFireStore\FireStoreDocument;
    
    $firestore = new FireStoreApiClient(
        'XXXXXX', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
    );
    $document = new FireStoreDocument();
    $document->setString('person', 'Jason'); // this works fine
    $document->setArray('my-array', array("cats","dogs","birds")); // this does not work
    $firestore->addDocument('people', $document);
    

    这是firestore。php

    <?php
    
    namespace PHPFireStore {
    
            class FireStoreDocument {
    
                    private $fields = [];
                    private $name = null;
                    private $createTime = null;
                    private $updateTime = null;
    
                    /**
                    Example:
                    {
                     "name": "projects/{project_id}/databases/(default)/documents/{collectionName}/{docu
                     "fields": {
                      "hello": {
                       "doubleValue": 3
                      }
                     },
                     "createTime": "2017-10-18T21:27:33.186235Z",
                     "updateTime": "2017-10-18T21:27:33.186235Z"
                    }
                    */
                    public function __construct($json=null) {
                            if ($json !== null) {
                                    $data = json_decode($json, true, 16);
                                    // Meta properties
                                    $this->name = $data['name'];
                                    $this->createTime = $data['createTime'];
                                    $this->updateTime = $data['updateTime'];
                                    // Fields
                                    foreach ($data['fields'] as $fieldName => $value) {
                                            $this->fields[$fieldName] = $value;
                                    }
                            }
                    }
    
                    public function getName() {
                            return $this->name;
                    }
    
                    public function setString($fieldName, $value) {
                            $this->fields[$fieldName] = [
                                    'stringValue' => $value
                            ];
                    }
    
                    public function setDouble($fieldName, $value) {
                            $this->fields[$fieldName] = [
                                    'doubleValue' => floatval($value)
                            ];
                    }
    
                    public function setArray($fieldName, $value) {
                            $this->fields[$fieldName] = [
                                    'arrayValue' => $value
                            ];
                    }
    
                    public function setBoolean($fieldName, $value) {
                            $this->fields[$fieldName] = [
                                    'booleanValue' => !!$value
                            ];
                    }
    
                    public function setInteger($fieldName, $value) {
                            $this->fields[$fieldName] = [
                                    'integerValue' => intval($value)
                            ];
                    }
    
                    public function setGeopoint($fieldName, $value) {
                            $this->fields[$fieldName] = [
                                    'geoPointValue' => array(
                                            'latitude' => (float)41.3819409,
                                            'longitude' => (float)-73.5299525
                                    )
                            ];
                    }
    
                    public function get($fieldName) {
                            if (array_key_exists($fieldName, $this->fields)) {
                                    return reset($this->fields);
                            }
                            throw new Exception('No such field');
                    }
    
                    public function toJson() {
                            return json_encode([
                                    'fields' => $this->fields
                            ]);
                    }
    
            }
    
            class FireStoreApiClient {
    
                    private $apiRoot = 'https://firestore.googleapis.com/v1beta1/';
                    private $project;
                    private $apiKey;
    
                    function __construct($project, $apiKey) {
                            $this->project = $project;
                            $this->apiKey = $apiKey;
                    }
    
                    private function constructUrl($method, $params=null) {
                            $params = is_array($params) ? $params : [];
                            return (
                                    $this->apiRoot . 'projects/' . $this->project . '/' .
                                    'databases/(default)/' . $method . '?key=' . $this->apiKey . '&' . h
                            );
                    }
    
                    private function get($method, $params=null) {
                            $curl = curl_init();
                            curl_setopt_array($curl, array(
                                CURLOPT_RETURNTRANSFER => 1,
                                CURLOPT_URL => $this->constructUrl($method, $params),
                                CURLOPT_USERAGENT => 'cURL'
                            ));
                            $response = curl_exec($curl);
                            curl_close($curl);
                            return $response;
                    }
    
                    private function post($method, $params, $postBody) {
                            $curl = curl_init();
                            curl_setopt_array($curl, array(
                                CURLOPT_RETURNTRANSFER => true,
                                CURLOPT_URL => $this->constructUrl($method, $params),
                                CURLOPT_HTTPHEADER => array('Content-Type: application/json','Content-Le
                                CURLOPT_USERAGENT => 'cURL',
                                CURLOPT_POST => true,
                                CURLOPT_POSTFIELDS => $postBody
                            ));
                            $response = curl_exec($curl);
                            var_dump($response);
                            curl_close($curl);
                            return $response;
                    }
    
                    private function put($method, $params, $postBody) {
                            $curl = curl_init();
                            curl_setopt_array($curl, array(
                                CURLOPT_RETURNTRANSFER => true,
                                CURLOPT_CUSTOMREQUEST => 'PUT',
                                CURLOPT_HTTPHEADER => array('Content-Type: application/json','Content-Le
                                CURLOPT_URL => $this->constructUrl($method, $params),
                                CURLOPT_USERAGENT => 'cURL',
                                CURLOPT_POSTFIELDS => $postBody
                            ));
                            $response = curl_exec($curl);
                            curl_close($curl);
                            return $response;
                    }
    
                    private function patch($method, $params, $postBody) {
                            $curl = curl_init();
                            curl_setopt_array($curl, array(
                                CURLOPT_RETURNTRANSFER => true,
                                CURLOPT_CUSTOMREQUEST => 'PATCH',
                                CURLOPT_HTTPHEADER => array('Content-Type: application/json','Content-Le
                                CURLOPT_URL => $this->constructUrl($method, $params),
                                CURLOPT_USERAGENT => 'cURL',
                                CURLOPT_POSTFIELDS => $postBody
                            ));
                            $response = curl_exec($curl);
                            curl_close($curl);
                            return $response;
                    }
    
                    private function delete($method, $params) {
                            $curl = curl_init();
                            curl_setopt_array($curl, array(
                                CURLOPT_RETURNTRANSFER => 1,
                                CURLOPT_CUSTOMREQUEST => 'DELETE',
                                CURLOPT_URL => $this->constructUrl($method, $params),
                                CURLOPT_USERAGENT => 'cURL'
                            ));
                            $response = curl_exec($curl);
                            curl_close($curl);
                            return $response;
                    }
    
                    public function getDocument($collectionName, $documentId) {
                            if ($response = $this->get("documents/$collectionName/$documentId")) {
                                    return new FireStoreDocument($response);
                            }
                    }
    
                    /**
                            This does not work
                    */
                    public function setDocument($collectionName, $documentId, $document) {
                            return $this->put(
                                    "documents/$collectionName/$documentId",
                                    [ ],
                                    $document->toJson()
                            );
                    }
    
                    public function updateDocument($collectionName, $documentId, $document, $documentExi
                            $params = [];
                            if ($documentExists !== null) {
                                    $params['currentDocument.exists'] = !!$documentExists;
                            }
                            return $this->patch(
                                    "documents/$collectionName/$documentId",
                                    $params,
                                    $document->toJson()
                            );
                    }
    
                    public function deleteDocument($collectionName, $documentId) {
                            return $this->delete(
                                    "documents/$collectionName/$documentId", []
                            );
                    }
    
                    public function addDocument($collectionName, $document) {
                            return $this->post(
                                    "documents/$collectionName",
                                    [],
                                    $document->toJson()
                            );
                    }
    
            }
    
    }
    

    此外,这是我正在使用的PHP版本:

    php -v
    PHP 7.1.10-1+ubuntu14.04.1+deb.sury.org+1 (cli) (built: Sep 29 2017 17:33:22) ( NTS )
    Copyright (c) 1997-2017 The PHP Group
    Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
        with Zend OPcache v7.1.10-1+ubuntu14.04.1+deb.sury.org+1, Copyright (c) 
    1999-2017, by Zend Technologies
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   gsposato    6 年前

    通过使用@JRLtechwriting提供的链接,我实现了这一点。 以下是链接: http://googlecloudplatform.github.io/google-cloud-php/#/docs/google-cloud/v0.53.0/firestore/firestoreclient

    在Ubuntu 14.04的命令行中,我必须这样做:

    sudo apt-get install php7.1-dev php-pear phpunit libz-dev
    sudo pecl install protobuf
    sudo pecl install grpc
    sudo composer require google/cloud
    # append BOTH apache2 php.ini AND command line php.ini with the following:
    # extension=protobuf.so
    # extension=grpc.so
    sudo apachectl graceful
    

    然后我编写了以下代码:

    <?php
    
    require "vendor/autoload.php"; // composer
    
    $path = "/xxx/firebase_auth.json"; // this file is provided by google
    $config = array(
        "projectId" => "xxx",
        "keyFile" => json_decode(file_get_contents($path), true)
    );
    $firestore = new FirestoreClient($config);
    $collection = $firestore->collection('people');
    $person = $collection->add([
        'person_id' => '3'
    ]);
    $document = $firestore->document('people/'.$person->id());
    $firestore->runTransaction(function (Transaction $transaction) use ($document) {
        $transaction->update($document, [
            ['path' => 'person', 'value' => 'Jason'],
            ['path' => 'my-array', 'value' =>array(                                                                              
                "cats",
                "dogs",
                "birds",
                )
            ],
        ]);
    });
    

    这一切都如期而至。

    另一方面,如果您使用的是带有内置事务类的框架,则在使用Google的Firestore SDK时需要做出特殊安排:

    use \Google\Cloud\Firestore\Transaction as FirestoreTransaction;
    

    这一行将改写为:

    $firestore->runTransaction(function (FirestoreTransaction $transaction) use ($document) {