Design a RESTful API in Laravel 5.2, using a resource that conceptually can contain other resources - api

First of all I am really not very familiar with the REST practice, and I am not very confident about the title of my question.
So I am trying to built a RESTful API using Laravel for a phonebook application. The phonebook may contain telephones of either employees (i.e real persons) or offices. For that reason I have three models
a Directorate with id and name fields,
an Employee with id and name fields and
a Telephone with id, tel, employee_id, directorate_id, description and type fields.
Telephones corresponding to a directorate's office have only the id, tel, directorate_id and description fields set, while the telephones corresponding to a person (i.e an employee) have set only the id, tel, employee_id, directorate_id, and type fields. That is how I separate them: a telephone having a description can only be an office's telephone, while a telephone having both the employee_id and the type_id set is an employee's telephone.
The models are related as follows:
an employee may have many telephones
a directorate, may have many telephones
class Directorate extends Model
{
public function telephones()
{
return $this->hasMany(Telephone::class);
}
public function employees()
{
return $this->hasMany(Employee::class);
}
}
class Employee extends Model
{
public function telephones()
{
return $this->hasMany(Telephone::class);
}
public function directorate()
{
return $this->belongTo(Directorate::class);
}
}
class Telephone extends Model
{
public function employee()
{
return $this->belongsTo(Employee::class);
}
}
My question is what should I a consider as my resource.
So far I am thinking of the following approach:
I shall use the concept of contact as resource. A contact may be the joined information of either an employee and a telephone, or a directorate and a telephone. For instance, a "contact" may contain the name of an employee with his related telephone numbers and telephone types, or it can contain the name of a directorate with the description of the telephone and the telephone number.
The "problem" with this approach is that I have ended up with (let's put it this way) two different types of resource: the employee's contacts and the directorate office's contacts, which contain slightly different information and thus, I need also to have different create and edit forms to interact with these two "types" of resources.
In order to implement the REST API, I am thinking of two different scenarios:
Use two different RESTful controllers, one EmployeeContacts and another OfficesContacts for separating conceptually the resource to an employee's and an office's resource, and accessing them through different URIs like:
example.com/phonebook/employees/{id}/edit
example.com/phonebook/offices/{id}/edit
example.com/phonebook/employees/create
etc...
Use a single RESTful controller, e.g. PhonebookContacts to access the resources through the same URIs as one resource (i.e. both employee's and office's contact resources now are considered to be just a "contact" resource)
//this refers to a contact resource that can be either an office's or a n employee's contact
example.com/phonebook/contact/{id}/edit
//this should list all resources (both employees and offices contacts)
example.com/phonebook/contact/
and then use conditional statements in the controller's create/store/edit/update methods to deal with them separately (e.g if an http POST request contains a description_id then it is an office contact and do this, or else if has an employee_id then it is an employee's contact so do that...)
I would like to hear your views, what of these two different scenarios do you consider to be better in the context of REST for my phonebook app? Would be better to think of a single "contact" resource and handle it using conditional statements with different return in the controller, or shall I separate the concept of "contact" to "employee's contact" and "office's contact" and use separate controllers and URI's to handle them?
Is there another approach that I could follow instead?

The way I would do it is with 2 different controllers for the simple reason of speed and responsiveness. Loading all contacts and filtering isn't as quick as loading the one part only.
However, you can always set in your controller the same return with different data. Such as EmployeeController#index returns view('contacts.index', compact('employeeContacts')), and OfficesController#index returns view('contacts.index', compact('officesContacts'))
EDIT:
Sorry, I have misread it...I thought you wanted to do the filtering in the view. Anyway, my practice is to do it separately, simply because the code is cleaner. If you want to make the whole REST more readable, you can put both resources in a group like so: Route::group(['prefix' => 'contact'], function(){ //routes here// });
So now you will have routes like:
example.com/contact/employees/
example.com/contact/offices/

I am not familiar at all with Laravel but since this question is about REST concepts (I have a small background on these) I should give it a try.
Since you are building a RESTful application, you must not consider others as human beings but only as machines. IMO the urls should determine the action that will be performed. Thus, by using different urls for different actions (perform a CRUD on a contact - either an Employee or a Directorate or SomethingElseInTheFuture) sounds good to me and fits the REST nice.
Hope this clarify the things for you!
[EDIT]
I believe jannis is right. It should be the verbs (GET, POST, PUT, PATCH etc) that make the action instead of the URLs. The urls are just respresenting the resources. My mistake. So both of your points of view are correct. It's just how convenient each approach is for your project (for now and for the near future of your project). IMO, I see #1 (two different restful controllers) more approchable.
Cheers and sorry for any misconception!

Related

how to recognize object's responsibility?

I'm new in OOP and I just started learning it. Its too complicated to determine the functionality of classes. Let's take an example:
We have an Address-book and an user want to add a new contact to it.
In this scenario we have 2 classes:
User: that determine the user that logged in.
Contact: A contact object that consists of Name, Address, Phone Number, etc
And the questions:
Who have to save a new contact?User class or Contact Class
If we try to check the user's permission before doing anything where is the best place for it?
Is it OK that these classes have a access to database?(Is it better to create 3rd class for doing query stuffs?)
Thanks for any good idea ;)
Usable distribution of "responsibility" is an OOP design and architecture decision with no single simple correct answer. For discussion refer to Stack Overflow question What is the single most influential book every programmer should read?
You'll learn the pros/cons by coding (using someone's design or creating your own design which does not work well).
However there are some useful/frequent distributions of responsibility already known as http://en.wikipedia.org/wiki/Software_design_pattern
In my opinion the only fixed fact is that each class/function/structure should have its responsibility clearly defined/documented - since the very first lines of code - and "do one thing and do it well"
Contacts are user specific. Thus every user object (class instance) should contain its own contacts object which is a container of contact (other user) objects, comprising in turn of name, address, phone etc.
class User {
String name;
String phone;
String address;
Contacts contacts;
....
}
class Contacts {
List<User> items;
}
The Contacts class should have the implementation of saving a new contact, which needs to be called from a User method, something like the following.
User u;
Contacts c = u.getContacts();
c.addContact(name, address, phone);
User's permissions should be checked in the User class.
The methods of these classes should interface with the database. For this each class method can open a new connection to a database and execute SQL queries. Example method of User cass:
User getContact(String name) {
Connection conn = getConnection();
....
PreparedStatement ps = con.prepareStatement("select * from Contacts where name = ?");
...
return userRcd;
}
1) Save new contact must the separate class, which working directly with database
2) Best place to check user permission - in user class of course
3) See the item 1:)
I recommend you get strong knowledge about SOLID principles, it's basics for good design.

Designing a rest url - filter with multiple params over entities (not last entity)

Let's say I have the following entities in my libraries app - Library Room, shelf, Book.
Where Room has N shelves, and shelves have N Books.
Now the following url brings me a list of books whose
library is 3, room no. is 5 and shelf no. is 43.
.../library/3/room/5/shelf/43/books
Assuming shelf 43 is unique per room only
(There is shelf 43 also in other rooms)
and Rooms are not unique (There's a few room no. 5 ) in the library.
Here is my questions:
I want to filter with more fields on the entities, here is what i want to do
(representation not in rest):
.../library/id=3&type=3/room/decade=21&topic=horror/shelf/location=east&/books
This is not rest.
How do I represent it in rest?
Notes:
I don't want to do this way
.../books&param1=X&param2=X&param3=X&param4=X
because not all params are related to books.
Couple of things that you need to look into while designing your apis.
1) are type, decade, topic etc required fields? if so, I will probably make them a part of the path itself, such as:
../libraries/{libraryId}/type/{typeId}/rooms/{roomId}/decades/{decadeId}/topics/{topicName}/shelves/{shelfId}/locations/{shelfLocation}/books
Here I am assuming that each library can have rooms which have unique room ids per library, each room can have shelves which has unique ids/locations per room (and so on and so forth). Yes, the url is pretty long, but that's kind of expected
2) if these fields are not required, you could use a different approach which is a bit less verbose but a bit more confusing for client developers who have never used such approach here. Here's a straight up example Restful Java with JAX-RS by Bill Burke
#Path("{first}-{last}")
#GET
#Produces("application/xml")
public StreamingOutput getCustomer(#PathParam("first") String firstName,
#PathParam("last") String lastName) {
...
}
Here, we have the URI path parameters {first} and {last}. If our HTTP request is
GET /customers/bill-burke, bill will be injected into the firstName parameter and
burke will be injected into the lastName parameter.
If we follow this somewhat academic approach (I have not seen this implemented on many platforms. Most platforms normally go with approach # 1, a more verbose but clear approach), your URL would look somewhat like this:
../libraries/{libraryId}-{typeId}/rooms/{roomId}-{decadeId}-{topicName}/shelves/{shelfId}-{shelfLocation}/books
This way, if the client developer doesn't pass in the non-required fields, you can handle it at the business logic level and assign these variables a default value, for example:
../libraries/3-/rooms/2-1-horror/shelves/1-/books
With this url, libraryId = 3, typeId = null (thus can be defaulted to it's default value) and so on and so forth. Remember that if libraryId is required field, then you might want to actually make it a part of the pathparam itself
Hope this helps!

Managing relationships in Laravel, adhering to the repository pattern

While creating an app in Laravel 4 after reading T. Otwell's book on good design patterns in Laravel I found myself creating repositories for every table on the application.
I ended up with the following table structure:
Students: id, name
Courses: id, name, teacher_id
Teachers: id, name
Assignments: id, name, course_id
Scores (acts as a pivot between students and assignments): student_id, assignment_id, scores
I have repository classes with find, create, update and delete methods for all of these tables. Each repository has an Eloquent model which interacts with the database. Relationships are defined in the model per Laravel's documentation: http://laravel.com/docs/eloquent#relationships.
When creating a new course, all I do is calling the create method on the Course Repository. That course has assignments, so when creating one, I also want to create an entry in the score's table for each student in the course. I do this through the Assignment Repository. This implies the assignment repository communicates with two Eloquent models, with the Assignment and Student model.
My question is: as this app will probably grow in size and more relationships will be introduced, is it good practice to communicate with different Eloquent models in repositories or should this be done using other repositories instead (I mean calling other repositories from the Assignment repository) or should it be done in the Eloquent models all together?
Also, is it good practice to use the scores table as a pivot between assignments and students or should it be done somewhere else?
I am finishing up a large project using Laravel 4 and had to answer all of the questions you are asking right now. After reading all of the available Laravel books over at Leanpub, and tons of Googling, I came up with the following structure.
One Eloquent Model class per datable table
One Repository class per Eloquent Model
A Service class that may communicate between multiple Repository classes.
So let's say I'm building a movie database. I would have at least the following following Eloquent Model classes:
Movie
Studio
Director
Actor
Review
A repository class would encapsulate each Eloquent Model class and be responsible for CRUD operations on the database. The repository classes might look like this:
MovieRepository
StudioRepository
DirectorRepository
ActorRepository
ReviewRepository
Each repository class would extend a BaseRepository class which implements the following interface:
interface BaseRepositoryInterface
{
public function errors();
public function all(array $related = null);
public function get($id, array $related = null);
public function getWhere($column, $value, array $related = null);
public function getRecent($limit, array $related = null);
public function create(array $data);
public function update(array $data);
public function delete($id);
public function deleteWhere($column, $value);
}
A Service class is used to glue multiple repositories together and contains the real "business logic" of the application. Controllers only communicate with Service classes for Create, Update and Delete actions.
So when I want to create a new Movie record in the database, my MovieController class might have the following methods:
public function __construct(MovieRepositoryInterface $movieRepository, MovieServiceInterface $movieService)
{
$this->movieRepository = $movieRepository;
$this->movieService = $movieService;
}
public function postCreate()
{
if( ! $this->movieService->create(Input::all()))
{
return Redirect::back()->withErrors($this->movieService->errors())->withInput();
}
// New movie was saved successfully. Do whatever you need to do here.
}
It's up to you to determine how you POST data to your controllers, but let's say the data returned by Input::all() in the postCreate() method looks something like this:
$data = array(
'movie' => array(
'title' => 'Iron Eagle',
'year' => '1986',
'synopsis' => 'When Doug\'s father, an Air Force Pilot, is shot down by MiGs belonging to a radical Middle Eastern state, no one seems able to get him out. Doug finds Chappy, an Air Force Colonel who is intrigued by the idea of sending in two fighters piloted by himself and Doug to rescue Doug\'s father after bombing the MiG base.'
),
'actors' => array(
0 => 'Louis Gossett Jr.',
1 => 'Jason Gedrick',
2 => 'Larry B. Scott'
),
'director' => 'Sidney J. Furie',
'studio' => 'TriStar Pictures'
)
Since the MovieRepository shouldn't know how to create Actor, Director or Studio records in the database, we'll use our MovieService class, which might look something like this:
public function __construct(MovieRepositoryInterface $movieRepository, ActorRepositoryInterface $actorRepository, DirectorRepositoryInterface $directorRepository, StudioRepositoryInterface $studioRepository)
{
$this->movieRepository = $movieRepository;
$this->actorRepository = $actorRepository;
$this->directorRepository = $directorRepository;
$this->studioRepository = $studioRepository;
}
public function create(array $input)
{
$movieData = $input['movie'];
$actorsData = $input['actors'];
$directorData = $input['director'];
$studioData = $input['studio'];
// In a more complete example you would probably want to implement database transactions and perform input validation using the Laravel Validator class here.
// Create the new movie record
$movie = $this->movieRepository->create($movieData);
// Create the new actor records and associate them with the movie record
foreach($actors as $actor)
{
$actorModel = $this->actorRepository->create($actor);
$movie->actors()->save($actorModel);
}
// Create the director record and associate it with the movie record
$director = $this->directorRepository->create($directorData);
$director->movies()->associate($movie);
// Create the studio record and associate it with the movie record
$studio = $this->studioRepository->create($studioData);
$studio->movies()->associate($movie);
// Assume everything worked. In the real world you'll need to implement checks.
return true;
}
So what we're left with is a nice, sensible separation of concerns. Repositories are only aware of the Eloquent model they insert and retrieve from the database. Controllers don't care about repositories, they just hand off the data they collect from the user and pass it to the appropriate service. The service doesn't care how the data it receives is saved to the database, it just hands off the relevant data it was given by the controller to the appropriate repositories.
Keep in mind you're asking for opinions :D
Here's mine:
TL;DR: Yes, that's fine.
You're doing fine!
I do exactly what you are doing often and find it works great.
I often, however, organize repositories around business logic instead of having a repo-per-table. This is useful as it's a point of view centered around how your application should solve your "business problem".
A Course is a "entity", with attributes (title, id, etc) and even other entities (Assignments, which have their own attributes and possibly entities).
Your "Course" repository should be able to return a Course and the Courses' attributes/Assignments (including Assignment).
You can accomplish that with Eloquent, luckily.
(I often end up with a repository per table, but some repositories are used much more than others, and so have many more methods. Your "courses" repository may be much more full-featured than your Assignments repository, for instance, if your application centers more around Courses and less about a Courses' collection of Assignments).
The tricky part
I often use repositories inside of my repositories in order to do some database actions.
Any repository which implements Eloquent in order to handle data will likely return Eloquent models. In that light, it's fine if your Course model uses built-in relationships in order to retrieve or save Assignments (or any other use case). Our "implementation" is built around Eloquent.
From a practical point of view, this makes sense. We're unlikely to change data sources to something Eloquent can't handle (to a non-sql data source).
ORMS
The trickiest part of this setup, for me at least, is determing if Eloquent is actually helping or harming us. ORMs are a tricky subject, because while they help us greatly from a practical point of view, they also couple your "business logic entities" code with the code doing the data retrieval.
This sort of muddles up whether your repository's responsibility is actually for handling data or handling the retrieval / update of entities (business domain entities).
Furthermore, they act as the very objects you pass to your views. If you later have to get away from using Eloquent models in a repository, you'll need to make sure the variables passed to your views behave in the same way or have the same methods available, otherwise changing your data sources will roll into changing your views, and you've (partially) lost the purpose of abstracting your logic out to repositories in the first place - the maintainability of your project goes down as.
Anyway, these are somewhat incomplete thoughts. They are, as stated, merely my opinion, which happens to be the result of reading Domain Driven Design and watching videos like "uncle bob's" keynote at Ruby Midwest within the last year.
I like to think of it in terms of what my code is doing and what it is responsible for, rather than "right or wrong". This is how I break apart my responsibilities:
Controllers are the HTTP layer and route requests through to the underlying apis (aka, it controls the flow)
Models represent the database schema, and tell the application what the data looks like, what relationships it may have, as well as any global attributes that may be necessary (such as a name method for returning a concatenated first and last name)
Repositories represent the more complex queries and interactions with the models (I don't do any queries on model methods).
Search engines - classes that help me build complex search queries.
With this in mind, it makes sense every time to use a repository (whether you create interfaces.etc. is a whole other topic). I like this approach, because it means I know exactly where to go when I'm needing to do certain work.
I also tend to build a base repository, usually an abstract class which defines the main defaults - basically CRUD operations, and then each child can just extend and add methods as necessary, or overload the defaults. Injecting your model also helps this pattern to be quite robust.
Think of Repositories as a consistent filing cabinet of your data (not just your ORMs). The idea is that you want to grab data in a consistent simple to use API.
If you find yourself just doing Model::all(), Model::find(), Model::create() you probably won't benefit much from abstracting away a repository. On the other hand, if you want to do a bit more business logic to your queries or actions, you may want to create a repository to make an easier to use API for dealing with data.
I think you were asking if a repository would be the best way to deal with some of the more verbose syntax required to connect related models. Depending on the situation, there are a few things I may do:
Hanging a new child model off of a parent model (one-one or one-many), I would add a method to the child repository something like createWithParent($attributes, $parentModelInstance) and this would just add the $parentModelInstance->id into the parent_id field of the attributes and call create.
Attaching a many-many relationship, I actually create functions on the models so that I can run $instance->attachChild($childInstance). Note that this requires existing elements on both side.
Creating related models in one run, I create something that I call a Gateway (it may be a bit off from Fowler's definitions). Way I can call $gateway->createParentAndChild($parentAttributes, $childAttributes) instead of a bunch of logic that may change or that would complicate the logic that I have in a controller or command.

nhibernate "multi key" mapping - bank accounts/adress data for different entities

I am searching for the right way to model the following situation with nhibernate:
bank account and/or address data cloud be linked to the following entities
Customer
Contract
Claim
*...
which are totally different, so that it cloud not linked to common parent.
At the moment, my only solution is the use of unique link tables for every constellation:
bank_to_customer
bank_to_contract
...
add_to_customer
add_to_contract
and
bank has mapped collections like
customers
contracts
...
address has equal collections like
customers
contracts
...
I have a bad feeling to solve the requirement to search for a bank account or street and show which entities are linked with the result set.
Maybe four results for "abc street" in adresse query than it is necessary to query all "add_" link tables four times to identify all links...
perhaps there is a better solution or modeling of the problem?
thank for any suggestion
maybe any / many-to-any Mapping adresse the problem
http://jzo001.wordpress.com/2013/01/21/nhibernate-many-to-any-mapping-composite-identifier-unidirectional-relationship/
but it is coupled with inheritance
use many-to-any with an interface
interface IHaveContacts
{
ICollection<Contact> Contacts { get; }
}
class Contact
{
ICollection<IHaveContacts> EntitiesWithContacts { get; private set; }
}
unfortunatly it is not supported with FNH as it seems. use hbm.xml for this mapping alone or edit the mapping before adding it to the config.

RESTful API - How do I return different results for the same resource?

Question
How do I return different results for the same resource?
Details
I have been searching for some time now about the proper way to build a RESTful API. Tons of great information out there. Now I am actually trying to apply this to my website and have run into a few snags. I found a few suggestions that said to base the resources on your database as a starting point, considering your database should be structured decently. Here is my scenario:
My Site:
Here is a little information about my website and the purpose of the API
We are creating a site that allows people to play games. The API is supposed to allow other developers to build their own games and use our backend to collect user information and store it.
Scenario 1:
We have a players database that stores all player data. A developer needs to select this data based on either a user_id (person who owns the player data) or a game_id (the game that collected the data).
Resource
http://site.com/api/players
Issue:
If the developer calls my resource using GET they will receive a list of players. Since there are multiple developers using this system they must specify some ID by which to select all the players. This is where I find a problem. I want the developer to be able to specify two kinds of ID's. They can select all players by user_id or by game_id.
How do you handle this?
Do I need two separate resources?
Lets say you have a controller name 'Players', then you'll have 2 methods:
function user_get(){
//get id from request and do something
}
function game_get(){
//get id from request and do something
}
now the url will look like: http://site.com/api/players/user/333, http://site.com/api/players/game/333
player is the controller.
user/game are the action
If you use phil sturgeon's framework, you'll do that but the url will look like:
http://site.com/api/players/user/id/333, http://site.com/api/players/game/id/333
and then you get the id using : $this->get('id');
You can limit the results by specifying querystring parameters, i.e:
http://site.com/api/players?id=123
http://site.com/api/players?name=Paolo
use phil's REST Server library: https://github.com/philsturgeon/codeigniter-restserver
I use this library in a product environment using oauth, and api key generation. You would create a api controller, and define methods for each of the requests you want. In my case i created an entirely seperate codeigniter instance and just wrote my models as i needed them.
You can also use this REST library to insert data, its all in his documentation..
Here is a video Phil threw together on the basics back in 2011..
http://philsturgeon.co.uk/blog/2011/03/video-set-up-a-rest-api-with-codeigniter
It should go noted, that RESTful URLs mean using plural/singular wording e.g; player = singular, players = all or more than one, games|game etc..
this will allow you to do things like this in your controller
//users method_get is the http req type.. you could use post, or put as well.
public function players_get(){
//query db for players, pass back data
}
Your API Request URL would be something like:
http://api.example.com/players/format/[csv|json|xml|html|php]
this would return a json object of all the users based on your query in your model.
OR
public function player_get($id = false, $game = false){
//if $game_id isset, search by game_id
//query db for a specific player, pass back data
}
Your API Request URL would be something like:
http://api.example.com/player/game/1/format/[csv|json|xml|html|php]
OR
public function playerGames_get($id){
//query db for a specific players games based on $userid
}
Your API Request URL would be something like:
http://api.example.com/playerGames/1/format/[csv|json|xml|html|php]