Tuesday, December 2, 2014

Re: Formatting of entities and maintaing different entity "versions"

There are a few ways of accomplishing this, but since we could say foursquare is "command based" (Depending on the url you visit you get compact or full) I would say the easiest is to apply data transformers from the controller, and use the "hidden properties" feature of the entities to display the correct amount of data:

The entity:

class Venue extends Entity {

  public function showCompact() {
      $this->_hidden = ['foo', 'bar', 'baz'];
  }
}

The Controller:

class VenuesController extends AppController {

   public function explore() {
       // The Venues should be in compact format for this action
       $venues = $this->Venues->find('myCustomFinder')->formatResults(new SpecialFormatter('compact'));
       $this->set('venues', $venues);
   }

}

The Formatter:

class SpecialFormatter {

   public function __construct($mode) {
     $this->mode = $mode;
   }

    public function __invoke($results) {
      return $results->map(function($entity) {
         if ($this->mode === 'compact') {
            $entity->showCompact();
         }
         return $entity;
      });
    }
}

When the results are rendered to son, each of th entities will only show the properties that are not hidden.
With a bit more work you can improve this idea so you can tell the formatter to also be applied in associations or any nested property with different modes.

On Tuesday, December 2, 2014 3:46:38 PM UTC+1, Steve Tauber wrote:
With the introduction of entities in v3, I think there is the potential to solve a problem that I see come up having to do with the consistent formatting/versioning of entities.

I have worked on a couple of projects that involve taking entities and creating different "versions" of the same entity. An example would be something like Foursquare's User Object which has a Mini Object, a Compact Object, and a Complete Object. [https://developer.foursquare.com/docs/responses/user]. After retrieving data, I want to take the entities returned and format them all to the correct type, including the related models; e.g. Photos have their own "versions".

If we were to recreate the Foursquare api in CakePhp, we can use the ORM to give us the correct fields and related data, but then we might still need to do formatting. For instance, Photos will have it's own "versions". This code could live as methods on the models. You could have User->formatMiniObject which then knows to return a stripped down entity. That User Mini Object would also convert the Photo field into a Photo Mini Object instead of a Photo Compact Object. This seems rather messy though.

In 2.x, I currently use Containable to limit my fields but then I have messy, non DRY code that is intersecting the fields I need, and then formatting data for the related models. I think it would be useful to somehow declare these different versions on the entity. You could say that a User Mini Object has id, firstName, lastName, and photo field which is a Photo Mini Object. In the Photo model, I could declare that in order to create a Photo Mini Object, I need to call a method which will use my ImageStorage component to find the URLs. Or Perhaps, it's just a simple entity with id and url directly from the database.

The main scenario where I've encountered this are building APIs with consistent data types which are returned. There might be users objects but due to permissions or privacy a subset of the data is returned to the end user. The API is rigidly defined and so the end user expects certain fields depending on the "version" of the entity returned.

Thoughts?

-- Steve

--
Like Us on FaceBook https://www.facebook.com/CakePHP
Find us on Twitter http://twitter.com/CakePHP

---
You received this message because you are subscribed to the Google Groups "CakePHP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cake-php+unsubscribe@googlegroups.com.
To post to this group, send email to cake-php@googlegroups.com.
Visit this group at http://groups.google.com/group/cake-php.
For more options, visit https://groups.google.com/d/optout.

No comments: