3

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:

  1. 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...

  2. 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?

ira
  • 5,569
  • 6
  • 30
  • 41
  • To design an API (service contract) you must consult your application's requirements first. What is its primary purpose? Is it a phone number repository or maybe it's centered around employees' and offices' data and the contact information is considered a secondary concern? What functionalities are you planning? – jannis Apr 14 '16 at 11:43
  • can use : [https://stackoverflow.com/questions/22694289/call-external-api-function-from-controller-laravel-4/22695523#22695523](https://stackoverflow.com/questions/22694289/call-external-api-function-from-controller-laravel-4/22695523#22695523) – mohammadreza gohari Nov 17 '18 at 09:00

2 Answers2

0

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/
Norgul
  • 4,613
  • 13
  • 61
  • 144
  • Could you please explain to me a little more what do you mean by "Loading all contacts and filtering isn't as quick as loading the one part only"? I mean, isn't it feasible using one controller, loading only the part of data I want (e.g. for the employee's contacts something like: $employees = Employee::whereHas('telephones', function ($query) { $query->where('description_id', null); }) ->with([ 'telephones' => function ($query) { $query->where('description_id', null); } ]) ->get(); and then return only this part to the view? – ira Apr 14 '16 at 09:13
  • @Norgul Your confusing implementation and the API design. These are completely different things. API structure has nothing to do with speed or responsiveness. These are related to the implementation. API is there to decouple the contract from implementation. – jannis Apr 14 '16 at 11:47
  • I am not confusing it, as stated, I have misread the text. I thought he was trying to do the filtering in the view, not in the controller. I have edited the answer accordingly – Norgul Apr 14 '16 at 12:30
0

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!

Community
  • 1
  • 1
nik_m
  • 11,825
  • 4
  • 43
  • 57
  • Could you please clarify what you mean by "you must not consider others as human beings but only as machines"? In addition, if I understand correctly, are you suggesting that it is better to build the application in the context of having two distinct kinds of resources (i.e. a service contact and an employee contact) and then make CRUD to each of them separately? – ira Apr 14 '16 at 09:58
  • 1
    This is a great answer about concepts of [REST](http://stackoverflow.com/questions/671118/what-exactly-is-restful-programming). I am just saying that REST (AFAIK) should connect browser with server and rarely user with server. And yes, you understand correctly. I suggest to use two distinct kinds of resources. – nik_m Apr 14 '16 at 10:05
  • 1
    @nik_m On the contrary - having the action embedded in the URL is not RESTful at all. **The URLs in REST should identify resources, not actions.** The actions are denoted by method verbs: e.g. _GET /offices/1_ gets the office resource representation, _POST /offices_ creates a new office resource in the offices collection. – jannis Apr 14 '16 at 11:56