Skip to content

Instantly share code, notes, and snippets.

@bravo-kernel
Last active December 17, 2015 06:49
Show Gist options
  • Save bravo-kernel/5568181 to your computer and use it in GitHub Desktop.
Save bravo-kernel/5568181 to your computer and use it in GitHub Desktop.
CakePHP RestKit Plugin - HAL responses when listing collections

##CakePHP RestKit plugin - HAL responses when listing collections##

More information about the HAL convention can be found at http://stateless.co/hal_specification.html

Examples:

  • Example 1: minimalistic response with resource-links only
  • Example 2: rich response using additional find() fields
  • Example 3: rich response with an _id field pointing to an internal resource (automatic)
  • Example 4: rich response with an _id field pointing to an external resource (manual)

##EXAMPLE 1##

Minimalistic index action, will only generate links to the related resources (ideal for caching)

public function index() {
	$result = $this->Country->find('all', array('fields' => array('id')));
	if ($result) {
		$this->set(array(
 			'Countries' => $result,
			'_serialize' => array('Countries')));
	}
}

URI: http://your.api.com/countries.json

{
   "_links":
   {
	   "self":
	   {
		   "href": "/countries"
	   }
   },
   "_embedded":
   {
	   "countries":
	   [
		   {
			   "_links":
			   {
				   "self":
				   {
					   "href": "/countries/1"
				   }
			   }
		   },
		   {
			   "_links":
			   {
				   "self":
				   {
					   "href": "/countries/2"
				   }
			   }
		   },
		   {
			   "_links":
			   {
				   "self":
				   {
					   "href": "/countries/3"
				   }
			   }
		   }
	   ]
   }
}

URI: http://your.api.com/countries.xml

<?xml version="1.0" encoding="UTF-8"?>
<resource href="/countries">
	<resource rel="country" href="/countries/1"/>
	<resource rel="country" href="/countries/2"/>
	<resource rel="country" href="/countries/3"/>
</resource>

EXAMPLE 2

Rich response using some extra find() fields

public function index() {
	$result = $this->Country->find('all', array('fields' => array('id', 'name', 'iso_alpha3')));
	if ($result) {
		$this->set(array(
			'Countries' => $result,
			'_serialize' => array('Countries')));
	}
}

URI: http://your.api.com/countries.json

{
   "_links":
   {
	   "self":
	   {
		   "href": "/countries"
	   }
   },
   "_embedded":
   {
	   "countries":
	   [
		   {
			   "_links":
			   {
				   "self":
				   {
					   "href": "/countries/1"
				   }
			   },
			   "name": "Netherlands",
			   "iso_alpha3": "NLD"
		   },
		   {
			   "_links":
			   {
				   "self":
				   {
					   "href": "/countries/2"
				   }
			   },
			   "name": "United States",
			   "iso_alpha3": "USA"
		   }
	   ]
   }
}

URI: http://your.api.com/countries.xml

<?xml version="1.0" encoding="UTF-8"?>
<resource href="/countries">
	<resource rel="country" href="/countries/1">
		<name>Netherlands</name>
		<iso_alpha3>NLD</iso_alpha3>
	</resource>
	<resource rel="country" href="/countries/2">
		<name>United States</name>
		<iso_alpha3>USA</iso_alpha3>
	</resource>
</resource>

EXAMPLE 3

Rich response with automagic linking to internal resources based on detected _id field(s).

In this case the currency_id field triggers the internal link generator.

public function index() {
	$result = $this->Country->find('all', array('fields' => array(
		'id', 'name', 'iso_alpha3', 'currency_id')));
		
	if ($result) {
		$this->set(array(
			'Countries' => $result,
			'_serialize' => array('Countries')));
	}
}

URI: http://your.api.com/countries.json

{
   "_links":
   {
	   "self":
	   {
		   "href": "/countries"
	   }
   },
   "_embedded":
   {
	   "countries":
	   [
		   {
			   "_links":
			   {
				   "self":
				   {
					   "href": "/countries/1"
				   },
				   "currency":
				   {
					   "href": "/currencies/1"
				   }
			   },
			   "name": "Netherlands",
			   "iso_alpha3": "NLD"
		   },
		   {
			   "_links":
			   {
				   "self":
				   {
					   "href": "/countries/2"
				   },
				   "currency":
				   {
					   "href": "/currencies/2"
				   }
			   },
			   "name": "United States",
			   "iso_alpha3": "USA"
		   }
	   ]
   }
}

URI: http://your.api.com/countries.xml

<?xml version="1.0" encoding="UTF-8"?>
<resource href="/countries">
	<resource rel="country" href="/countries/1">
		<link rel="currency" href="/currencies/1"/>
		<name>Netherlands</name>
		<iso_alpha3>NLD</iso_alpha3>
	</resource>
	<resource rel="country" href="/countries/2">
		<link rel="currency" href="/currencies/2"/>
		<name>United States</name>
		<iso_alpha3>USA</iso_alpha3>
	</resource>
</resource>

EXAMPLE 4

Rich response where we manually flag an _id field as 'foreign' because it points to an external resource (not hosted by our CakePHP HalKit API).

In this real-life example the geoname_id can be used for various calls to the ws.geonames.org API so we choose to provide the id as a value (and not as a resource-link). This way the API-consumer can use it as he sees fit, e.g.

Controller function:

public function index() {
	$result = $this->Country->find('all', array('fields' => array('id', 'name', 'iso_alpha3', 'geoname_id')));
	if ($result) {
		$this->set(array(
		    'Countries' => $result,
		    '_serialize' => array('Countries'),
		    'options' => array(
				'foreignFields' => array('geoname_id'))));
	}
}

URI: http://your.api.com/countries.json

{
   "_links":
   {
       "self":
       {
           "href": "/countries"
       }
   },
   "_embedded":
   {
       "countries":
       [
           {
               "_links":
               {
                   "self":
                   {
                       "href": "/countries/1"
                   }
               },
               "name": "Netherlands",
               "iso_alpha3": "NLD",
               "geoname_id": "2750405"
           },
           {
               "_links":
               {
                   "self":
                   {
                       "href": "/countries/2"
                   }
               },
               "name": "United States",
               "iso_alpha3": "USA",
               "geoname_id": "6252001"
           },
       ]
   }
}

URI: http://your.api.com/countries.xml

<?xml version="1.0" encoding="UTF-8"?>
<resource href="/countries">
	<resource rel="country" href="/countries/1">
		<name>Netherlands</name>
		<iso_alpha3>NLD</iso_alpha3>
		<geoname_id>2750405</geoname_id>
	</resource>
	<resource rel="country" href="/countries/2">
		<name>United States</name>
		<iso_alpha3>USA</iso_alpha3>
		<geoname_id>6252001</geoname_id>
	</resource>
</resource>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment