Skip to content

Handle bulk Item updates in single API Request - PUT #100

@mfoolio

Description

@mfoolio

Attempting to update multiple ZohoBooks "Item" records with the "update" method quickly leads to API rate limits.

Using a PUT to the bare "/items" with a JSON object of many Item records will update them all with a single API call. The reply data is a JSON array with single top-level array of "items" with each record being the full updated individual Item and also the response "Code" and "Message" that would normally be returned from a single Item's update/PUT call.

While this ZohoBooksApi module allows to send an update to the bare "/items" by providing "null" as the id to the ->update() method (which in turns sends it to ->put()), the current release does not properly handle the resulting data response from the Zoho API.

Two issues presented:

  • Client.php - processResult() function does not have a case to handle a valid JSON response without a "Code" and "Message" at the top level, and
  • Module.php - update() function is only set up to handle and return a single Model Item from make()

To resolve for immediate use I modified code as follows:

  • processResult() in Client.php to accept the case where the data returned is a JSON object but does not have a top-level "Code" field.
        if (!$result) {
            // All ok, probably not json, like PDF?
            if ($response->getStatusCode() >= 200 && $response->getStatusCode() <= 299) {
                return (string)$response->getBody();
            }

            throw new ErrorResponseException($response->getReasonPhrase(), $response->getStatusCode());
        }

        if (isset($result['code']))
        {
            if ($result['code'] != 0)
            {
                throw new ErrorResponseException('Response from Zoho is not success. Message: ' . $result['message'], $result['code'] ?? $response->getStatusCode());
            } else
            {
                // All OK
                return $result;
            }
        }

        // All OK, JSON and likely bulk update with individual response codes
        return $result;
    }
  • update() in Module.php to test for a "null" $id, and if so to just return the decoded JSON array.
    public function update($id, $data, $params = [])
    {
        $data = $this->client->put($this->getUrl(), $id, $data, $params);

        if ($id != null)
        {
            // Updated single object
            $data = $data[$this->inflector->singularize($this->getResourceItemKey())];
            return $this->make($data);
        } else
        {
            // Updated muliple objects, return collection
            // case for bulk ie. update PUT to /items

            // body is top level of module name i.e. 'items'
            // array of each object that was submitted, 'code' and 'message' is in each sub object

            return $data[$this->getResourceKey()];
        }
    }

Would it be more desirable to create another Module method such as updateMany() instead of passing in a null id?
Are there consequences or other cases where processResult() shouldn't just return the JSON data object?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions