2

Apigility: How to render embedded objects?

 2 years ago
source link: https://www.codesd.com/item/apigility-how-to-render-embedded-objects.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Apigility: How to render embedded objects?

advertisements

How do I render embedded objects in Apigility? For example, if I have a 'user' object and it composes a 'country' object, should I be rendering the 'country' object as an embedded object? And how should I do this?

I am using the Zend\Stdlib\Hydrator\ArraySerializable. My getArrayCopy() method simply returns an array of properties that I want exposed. The array keys are the property names. The array values are the property values. In the case of user->country, the value is an object, not a scalar.

When I return the user object from UserResource->fetch(), here's how it is rendered:

{
  "id": "1",
  "firstName": "Joe",
  "lastName": "Bloggs",
  "status": "Active",
  "email": "[email protected]",
  "country": {
    "code": "AU",
    "name": "Australia"
  },
  "settings": "0",
  "_links": {
    "self": {
      "href": "http://api.mydomain.local/users/1"
    }
  }
}

Note that 'country' is not in an _embedded field. If it is supposed to be in _embedded, I would have thought that Apigility would automatically do that (since it automatically adds the _links object).

As a related issue, how do I go about returning other rel links, such as back, forward, etc?


The easiest way to get Apigility to render embedded resources is when there is an API/resource associated to the embedded object. What I mean for your example is that you'd have an API resource that has a country entity. In that case, if your getArrayCopy returned the the CountryEntity, Apigility would render it automatically as an embedded resource.

If your getArrayCopy is returning country as an array with code and name, you'll end up with what you saw.

For the other part, the rel links for first, last, prev and next will come from the fetchAll method when you return a Paginator. Your collection extends from this already, but it needs an adapter. The code could look something like this:

public function fetchAll($params)
{
    // Return a \Zend\Db\Select object that will retrieve the
    // stuff you want from the database
    $select = $this->service->fetchAll($params);

    $entityClass = $this->getEntityClass();
    $entity      = new $entityClass();

    $hydrator  = new \Zend\Stdlib\ArraySerializable();
    $prototype = new \Zend\Db\ResultSet\HydratingResultSet($hydrator, $entity);
    $paginator = new \Zend\Paginator\Adapter\DbSelect($select, $this->sql, $prototype);

    $collectionClass = $this->getCollectionClass();
    return new $collectionClass($paginator);
}

There are other paginator adapters as well - an ArrayAdapter which will take in an array of however big and then paginate it so you only get the desired number of results. The downside to this if you use it with database results, you'll potentially be retrieving and discarding a lot of results. The DbSelect paginator will modify the $select object to add the limit and order clause automatically so you only retrieve the bits you need. There are also adapters if you're using DbTableGateway, Iterators or even callbacks. You can also implement your own of course.

Hope this helps. If you have more specific needs or clarification, please comment and I'll do my best.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK