jjwdesign
jjwdesign

Reputation: 3322

Codeigniter REST API many to many Relationships?

I'm working on a REST API using Codeigniter and Phil Sturgeon's REST API Library.

https://github.com/philsturgeon/codeigniter-restserver

I've have the REST API working correctly, but now I'm wondering about modeling/REST for the relationships. For example, I have a many to many relationship between Contacts and Collections.

Format (excluding ?format=json)

GET
/rest_api/contact/{id}
GET
/rest_api/collection/{id}

Should the Relationships (m-m) be considered REST resources, such as?

GET (One)
/rest_api/contact_collection/{id}
GET (Collection/All)
/rest_api/contacts_collections/{contact_id}/{collection_id}
PUT (Save)
/rest_api/contact_collection/{contact_id}/{collection_id}
DELETE
/rest_api/contact_collection/{contact_id}/{collection_id}

Note, with Phil's CodeIngiter REST API, I don't think I can split it apart like:

PUT
/rest_api/contact/{contact_id}/collection/{collection_id}

I'm also questioning where/how the ID's should appear. Should the two ID's be part of the URL requested or be part of the PUT/POST data?

Upvotes: 0

Views: 1476

Answers (3)

bitdanh
bitdanh

Reputation: 1

Thanks,

CodeIgniter-RestServer

♦♦♦Change Log

♦ Download Version 2.5: https://github.com/chriskacerguis/codeigniter-restserver/tree/v2.5

  • Instead of just seeing item, item, item, the singular version of the basenode will be used if possible. Example.
  • Re-factored to use the Format library, which will soon be merged with CodeIgniter.
  • Fixed Limit bug (limit of 5 would allow 6 requests).
  • Added logging for invalid API key requests.
  • Changed serialize to serialized.
  • Changed all visibility 'private' to 'protected'.
  • MIME's with character encodings on the end will now work.
  • Fixed PUT arguments. Once again just sending a body query string works. Example
  • Fixed up all .foo extensions to work when no get arguments provided, and moved .html to Format library.
  • Updated key.php example to use config_item('rest_keys_table') instead of hardcoded 'keys' table name.
  • Updated REST_Controller to use config_item('rest_limits_table') instead of hardcoded 'limits'.

Upvotes: 0

Nicholas Shanks
Nicholas Shanks

Reputation: 10981

I would suggest modelling this as a collections property of the contact, to which you POST IDs. i.e.

GET /collections/{id}

 

GET /contacts/{id}/collections

 

POST /contacts/{id}/collections

or better yet, instead of POST, use LINK and UNLINK (https://datatracker.ietf.org/doc/html/draft-snell-link-method-01):

LINK /contacts/{id}
Link: </collections/{id}>;rel="collection"

(collection is an IANA-defined relation: http://www.iana.org/assignments/link-relations)

Upvotes: 1

jjwdesign
jjwdesign

Reputation: 3322

Nicholas, I upvoted your answer. Here's what I've gone with so far. Let me know if you think I'm on the right path.

# URI's Explained for base "rest_api" (controller)

# collections resource
/collections/{id}

# contacts resource
/contacts/{id}

# collections contacts subresource
/collections/{collection_id}/contacts/{id}
Routed to 
==> /contacts/id/{id}/collection_id/{collection_id} 

In Restful-terms it helps a lot in not thinking of SQL and joins but more into collections, sub-collections and traversal.

Some examples:

# getting contact 3 who is in collection 1
# or simply checking whether contact 3 is in that collection (200 vs. 404)
GET /collections/1/contacts/3   ==>   /contacts/id/3/collection_id/1

# getting contact 3 who is also in collection 3
GET /collections/3/contacts/3   ==>   /contacts/id/3/collection_id/3

# adding contact 3 also to collection 2 (RELATIONSHIP)
PUT /collections/2/contacts/3   ==>   /contacts/id/3/collection_id/2

# getting all collections of contact 3
GET /contacts/3/collections

# remove contact 3 from collection 1 (RELATIONSHIP)
DELETE /collections/1/contacts/3

# collection has a new contact, who is not yet added
POST /contacts
# from payload you get back the contacts insert id (44), now place contact in collection 1 (RELATIONSHIP)
PUT /collections/1/contacts/44

As you see I'm not using POST for placing contacts to collections but PUT, which handles the n:n relationship of contacts to collections.

PHP CodeIgniter Routes used are as follows. I'm really not sure if this is needed, but allows for the pretty URI's mentions above.

// Collections
$route['rest_api/collections/(:num)'] = "rest_api/collections/id/$1";

// Collection Contacts Subresource
$route['rest_api/collections/(:num)/contacts'] = "rest_api/contacts/collection_id/$1";
$route['rest_api/collections/(:num)/contacts/(:num)'] = "rest_api/contacts/id/$2/collection_id/$1";

Some of the rest_api controller methods get a little long, but it seems to work. I have to get the URI request params and the query string parmas, if used. Phil's CodeIgniter REST API had to be tweeked a bit to make sure to get the URI params when doing a PUT or DELETE request, as the values only existed in the $this->get() method; strange.

Upvotes: 0

Related Questions