Skip to content

t1mmen/CakePHP-Serializers

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CakePHP-Serializers

Software License Build Status Total Downloads

An object oriented solution to serialize CakePHP response to JSON and correspondingly deserialize JSON into CakePHP data arrays.

This plugin is designed to match the Ember Data and the DS.ActiveModelAdapter for serialization and deserialization of CakePHP generated responses.

Questions on any implementation details can be answered typically using the Test Cases as the final authoritative answer.

This is currently not fully production ready - be warned bugs/issues may exist.

This README is split into the following sections, with additional README documents covering certain topics.

  1. Base Use Case
  2. Requirements
  3. Installation
  4. Basic Setup
  5. Error and Exception Handling Setup
  6. Custom Bake Templates
  7. Advanced Examples
  8. Contributing
  9. License
  10. Copyright

Additional README Documents:

  1. Serialization
  2. Deserialization
  3. Exceptions

Basic Use Case

The basic concept for this plugin is to create an end to end solution for serializing and deserializing CakePHP respones into JSON. This plugin is primarily designed around the use of Ember and Ember Data.

So serializing a CakePHP model data array:

$data = array(
	'User' => array(
		'id' => 1,
		'username' => 'testusername',
		'first_name' => 'first',
		'last_name' => 'last',
		'is_active' => true,
	)
);

into:

{
	"user": {
		"id": 1,
		"username": "testusername",
		"first_name": "first",
		"last_name": "last",
		"is_active": true,
	}
}

And to perform the reverse, by deserializing data passed in the request body:

{
	"users": {
		"id": 1,
		"username": "testusername",
		"first_name": "first",
		"last_name": "last",
		"is_active": true,
	}
}

or:

{
	"user": {
		"id": 1,
		"username": "testusername",
		"first_name": "first",
		"last_name": "last",
		"is_active": true,
	}
}

into

$this->request->data = array(
	'User' => array(
		'id' => 1,
		'username' => 'testusername',
		'first_name' => 'first',
		'last_name' => 'last',
		'is_active' => true,
	)
);

Requirements

  • PHP >= 5.4.0
  • CakePHP >= 2.3

Installation

Composer

  • Run this shell command
php composer.phar require loadsys/cakephp_serializers "dev-master"

Git

git clone git@github.com:loadsys/CakePHP-Serializers.git Plugin/Serializers

Basic Setup

Load the plugin and be sure that bootstrap is set to true:

// Config/boostrap.php
CakePlugin::load('Serializers', array('bootstrap' => true));
// or
CakePlugin::loadAll(array(
	'Serializers' => array('bootstrap' => true),
));

If you are planning on using this plugin, to deserialize data in an HTTP request a few other changes are required:

// Config/boostrap.php
Configure::write('Dispatcher.filters', array(
	'Serializers.DeserializerFilter',
));

When deserializing data and setting your CakePHP controller to respond to REST HTTP requests you will also need to add:

// Config/routes.php
Router::mapResources(array(
	'{controller_name}',
));
Router::parseExtensions('json');

The CakePHP book has more information on doing REST APIs with CakePHP and this feature.

Error and Exception Handling Setup

Errors and Exceptions can also be handled with this plugin.

Modify your app/Config/core.php file to use the Custom Exceptions/Error handling in this plugin with this code:

Configure::write('Error', array(
	'handler' => 'EmberDataError::handleError',
	'level' => E_ALL & ~E_DEPRECATED,
	'trace' => true
));

Configure::write('Exception', array(
	'handler' => 'EmberDataError::handleException',
	'renderer' => 'Serializers.EmberDataExceptionRenderer',
	'log' => true
));

This does two things:

  • Errors and Exceptions get output as correctly formatted JSON
  • Allows the use of Custom Exceptions that match Ember Data exceptions for error cases

Custom Bake Templates

There are custom bake templates included in this project for baking your CakePHP Controller classes. Use the serializers template when baking a Controller, to generate a Controller to work with the Serializers Plugin.

The Custom Bake Templates include using the Custom Exception Classes from the above section to provide feedback that matches Ember Data's expectations.

Advanced Examples

We can serialize both multiple records:

$data = array(
	'User' => array(
		0 => array(
			'id' => 1,
			'username' => 'testusername',
			'first_name' => 'first',
			'last_name' => 'last',
			'is_active' => true,
		),
		1 => array(
			'id' => 2,
			'username' => 'testusername',
			'first_name' => 'first',
			'last_name' => 'last',
			'is_active' => true,
		),
	)
);

into:

{
	"users": [
		{
			"id": 1,
			"username": "testusername",
			"first_name": "first",
			"last_name": "last",
			"is_active": true,
		},
		{
			"id": 2,
			"username": "testusername",
			"first_name": "first",
			"last_name": "last",
			"is_active": true,
		},
	]
}

And serialize sub model records, even if there are multiple records:

$data = array(
	'User' => array(
		0 => array(
			'id' => 1,
			'username' => 'testusername',
			'first_name' => 'first',
			'last_name' => 'last',
			'is_active' => true,
			'SecondaryModel' => array(
				"something" => "blahh",
			),
		),
		1 => array(
			'id' => 2,
			'username' => 'testusername',
			'first_name' => 'first',
			'last_name' => 'last',
			'is_active' => true,
			'SecondaryModel' => array(
				0 => array(
					"something" => "teasdf",
				),
				1 => array(
					"something" => "fgdfghdfg",
				),
			),
		),
	)
);

into

{
	"users": [
		{
			"id": 1,
			"username": "testusername",
			"first_name": "first",
			"last_name": "last",
			"is_active": true,
			"secondary_models": {
				"something": "blahh",
			}
		},
		{
			"id": 2,
			"username": "testusername",
			"first_name": "first",
			"last_name": "last",
			"is_active": true,
			"secondary_models": [
				{
					"something": "teasdf",
				},
				{
					"something": "fgdfghdfg",
				}
			]
		},
	]
}

The same with deserialize both multiple records:

{
	"users": [
		{
			"id" : 1,
			"username": "testusername",
			"first_name": "first",
			"last_name": "last",
			"is_active": true,
		},
		{
			"id": 2,
			"username": "testusername",
			"first_name": "first",
			"last_name": "last",
			"is_active": true,
		},
	]
}

into

$this->request->data = array(
	'User' => array(
		0 => array(
			'id' => 1,
			'username' => 'testusername',
			'first_name' => 'first',
			'last_name' => 'last',
			'is_active' => true,
		),
		1 => array(
			'id' => 2,
			'username' => 'testusername',
			'first_name' => 'first',
			'last_name' => 'last',
			'is_active' => true,
		),
	)
);

And deserialize sub model records, even if there are multiple records:

{
	"users": [
		{
			"id": 1,
			"username": "testusername",
			"first_name": "first",
			"last_name": "last",
			"is_active": true,
			"secondary_models": {
				"something": "blahh",
			}
		},
		{
			"id": 2,
			"username": "testusername",
			"first_name": "first",
			"last_name": "last",
			"is_active": true,
			"secondary_models": [
				{
					"something": "teasdf",
				},
				{
					"something": "fgdfghdfg",
				}
			]
		},
	]
}

into

$this->request->data = array(
	'User' => array(
		0 => array(
			'id' => 1,
			'username' => 'testusername',
			'first_name' => 'first',
			'last_name' => 'last',
			'is_active' => true,
			'SecondaryModel' => array(
				"something" => "blahh",
			),
		),
		1 => array(
			'id' => 2,
			'username' => 'testusername',
			'first_name' => 'first',
			'last_name' => 'last',
			'is_active' => true,
			'SecondaryModel' => array(
				0 => array(
					"something" => "teasdf",
				),
				1 => array(
					"something" => "fgdfghdfg",
				),
			),
		),
	)
);

If there is a second top level model in the data to be serialized it is moved to a property of the first model

$data = array(
	'User' => array(
		'id' => 1,
		'username' => 'testusername',
		'first_name' => 'first',
		'last_name' => 'last',
		'is_active' => true,
	),
	'SecondModel' => array(
		'id' => 1,
		'name' => 'asdflkjasdf',
	),
);

into:

{
	"user": {
		"id": 1,
		"username": "testusername",
		"first_name": "first",
		"last_name": "last",
		"is_active": true,
		"second_model": {
			'id': 1,
			'name': 'asdflkjasdf',
		}
	}
}

If there is a second top level model in the data to be deserialized, it is ignored:

{
	"users": {
		"id": 1,
		"username": "testusername",
		"first_name": "first",
		"last_name": "last",
		"is_active": true,
	},
	"second_models": {
		"id": 1,
		"something": "data",
	}
}

into

$this->request->data = array(
	'User' => array(
		'id' => 1,
		'username' => 'testusername',
		'first_name' => 'first',
		'last_name' => 'last',
		'is_active' => true,
	)
);

Contributing

Reporting Issues

Please use GitHub Isuses for listing any known defects or issues.

Development

When developing this plugin, please fork and issue a PR for any new development.

The Complete Test Suite for the Plugin can be run via this command:

./lib/Cake/Console/cake test Serializers AllSerializers

License

MIT

Copyright

Loadsys Web Strategies 2015

About

CakePHP JSON API response serializers

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • PHP 100.0%