Formatting BEdita objects¶
Introducing the ApiFormatter
Component¶
To respond with consistent data the BEdita object types are transformed
and formatted using the ApiFormatter
Component that deals with
cleaning objects from useless data and casting and trasforming some
fields in correct format.
If you have a look at /objects/:id
response you’ll see that fields
as ‘id’ are integer other like ‘latitude’ and ‘longitude’ of geo tag
are float and dates are formatted in ISO-8601. ApiFormatter
Component with a little help from Models takes care of it.
When you load an object or list of objects you should always use the
ApiFromatter
Component to have data always formatted in the same
way.
// load an object
$object = $this->loadObj($id);
$result = $this->ApiFormatter->formatObject($object);
// in $result['object'] you have the formatted object
// list of objects
$objects = $this->loadSectionObjects($id, array('itemsTogether' => true));
$result = $this->ApiFormatter->formatObjects($objects['children']);
// in $result['objects'] you have the formatted objects
ApiFormatter::formatObject()
and ApiFormatter::formatObjects()
accept as second argument an array of options with which it is possible
add to the formatted object the count of relations and children.
$result = $this->ApiFormatter->formatObject($object, array(
'countRelations' => true,
'countChildren' => true
));
By default no count is done.
Help ApiFormatter to cast object fields in the right way¶
When formatting BEdita object ApiFormatter
asks help to related
object type Model to know which fields have to be cast in the right
type. Basically every object type returns an array of fields that are
defined in database as ‘integer’, ‘float’, ‘date’, ‘datetime’,
‘boolean’. This array is returned from
BEAppObjectModel::apiTransformer()
method and it is something
similar to
array(
'id' => 'integer',
'start_date' => 'datetime',
'end_date' => 'datetime',
'duration' => 'integer',
'object_type_id' => 'integer',
'created' => 'datetime',
'modified' => 'datetime',
'valid' => 'boolean',
'user_created' => 'integer',
'user_modified' => 'integer',
'fixed' => 'boolean',
'GeoTag' => array(
'id' => 'integer',
'object_id' => 'integer',
'latitude' => 'float',
'longitude' => 'float',
'gmaps_lookat' => array(
'latitude' => 'float',
'longitude' => 'float',
'zoom' => 'integer',
)
)
'Tag' => array(
'id' => 'integer',
'area_id' => 'integer',
'object_type_id' => 'integer',
'priority' => 'integer',
'parent_id' => 'integer',
),
'Category' => array(
'id' => 'integer',
'area_id' => 'integer',
'object_type_id' => 'integer',
'priority' => 'integer',
'parent_id' => 'integer',
)
)
By default only tables that form the object chain plus ‘categories’,
‘tags’ and ‘geo_tags’ are automatically returned, but that method can
be overridden to customize the result. For example the Event
model
add to basic transformer the DateItem
transformer:
public function apiTransformer(array $options = array()) {
$transformer = parent::apiTransformer($options);
$transformer['DateItem'] = $this->DateItem->apiTransformer($options);
return $transformer;
}
The ApiFormatter
uses these transformers merged to common object
transformer ApiFormatterComponent::$transformers['object']
to present
consistent data to client. It is possible to use some special
transformer types that are:
underscoreField
that underscorize a camelcase field maintaining value unchangedintegerArray
that cast to integer all array values
Remove unwanted fields¶
Another useful task of ApiFormatter
is to clean unwanted fields from
data exposed to client. To do that it uses
ApiFormatter::$objectFieldsToRemove
array that can be customized
through configuration or on the fly in controller.
Add fields to remove from configuration¶
In config/frontend.ini.php
or config/frontend.cfg.php
is
possible to customize which fields exposed by default you want to remove
from results.
$config['api'] = array(
'baseUrl' => '/api/v1',
...
'formatting' => array(
'fields' => array(
// fields that should be added
// to ApiFormattingComponent::objectFieldsToRemove
// i.e. removed from formatted object
'remove' => array(
'description',
'title',
'Category' => array('name'),
'GeoTag' => array('title'),
'Tag'
)
)
)
);
In this way you say to ApiFormatter
that ‘description’, ‘title’,
‘name’ of ‘Category’, ‘title’ of ‘GeoTag’ and all ‘Tag’ array must be
cleaned from final results. Every time ApiFormatter::formatObject()
or ApiFormatter::formatObjects()
is called the data are cleaned up
using ApiFormatter::cleanObject()
.
Add fields to remove on the fly¶
In your ApiController
you can decide in every moment to change which
fields remove from results using
ApiFormatter::objectFieldsToRemove()
method.
// get the current value
$currentFieldsToRemove = $this->ApiFormatter->objectFieldsToRemove();
// to ovveride all. It completely replaces current fields to remove with new one
$this->ApiFormatter->objectFieldsToRemove(
array(
'title',
'description'
),
true
);
// to add new fields to remove
$this->ApiFormatter->objectFieldsToRemove(array(
'remove' => array('title', 'description')
));
Keep fields that are removed by default¶
Sometime you could want to present to client some fields that normally are cleaned up. Likewise to what seen with fields to remove, it is possible do it from configuration or on the fly.
Add fields to keep from configuration¶
In config/frontend.cfg.php
$config['api'] = array(
'baseUrl' => '/api/v1',
...
'formatting' => array(
'fields' => array(
// fields that should be removed
// to ApiFormattingComponent::objectFieldsToRemove
// i.e. kept in formatted object
'keep' => array(
'fixed',
'ip_created',
'Category' => array('object_type_id', 'priority')
)
)
)
);
In this way you say to ApiFormatter
that ‘fixed’, ‘ip_created’ and
‘object_type_id’, ‘priority’ of ‘Category’ must be preserved and
presented to client.
Add fields to keep on the fly¶
In your ApiController
// to keep fields
$this->ApiFormatter->objectFieldsToRemove(array(
'keep' => array('ip_created', 'fixed')
));
It is possible to mix ‘remove’ and ‘keep’ options both in configuration and in controller.