Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to design laravel 5.1 application for web client and native mobile apps

I want to make a Laravel 5.1 application for web and api's for mobile apps. I want to return json for api request and view for web browser. Currently I have setup different routes and different controllers. In this approach I'm repeating the code. I don't know what is the best approach to design this architecture. Also, I've gone through few similar threads which recommends using angular.js for web browser.

// web controller
Route::resource('product', 'ProductController');

// api controller 
Route::group(['prefix' => 'api'], function() {
    Route::resource('product', 'APIProductController');
});
like image 506
Ashish Avatar asked Aug 07 '15 05:08

Ashish


2 Answers

You can have 2 basic approaches:

  • Keep separate routes and controllers, but move all your common controller's code into a service. This is probably the cleanest and the most flexible solution, as it makes it very easy to update API and web methods independently in the future.
  • Or you can route both api and web requests to the same controller, pass the Request object into it, and then based on some request attribute decide which response to return, json or html.

For the 2nd approach you could for example do it like this:

// web controller
Route::resource('product', 'ProductController');

// api controller 
Route::group(['prefix' => 'api'], function() {
    Route::resource('product', 'ProductController');
});

// and in the ProductController you have
public function index(Request $request) 
{
    // do some stuff...

    if ($request->segment(1) === 'api') { // route prefix was api
        // return json
    } else {
        // return the view
    }
}

You could also use $request->wantsJson() method to check on Accept: header or you could pass a special GET variable (e.g. ?_format=json) with all API calls to define the response format should be json, as already suggested by @Bogdan Kuštan. IMHO if you already use api prefix on your urls it's more reliable and cleaner to just check on that.

like image 122
ivanhoe Avatar answered Oct 20 '22 00:10

ivanhoe


One way would be to use content negotiation approach. You would pass header Accept: application/json and then Your app would return json formatted response. however some proxy servers do not respect content negotiation, then Your app would break (You can read more why Drupal dropped content negotiation here).

Another possibility is tu use some GET variable to return requested format, for example: /api/product?format=json

Also You can pass variable from /api calls:

Route::get('/api/product', ['as' => 'product', function(){
    return App::make('ProductController')->index('json');
}]);

public function index($format) {
    // Your controller code

    if ($format == 'json') {
        // return JSON
    }

    // return HTML
}

Or You can parse URI directly and see if it starts with /API (do not recommend). My choices would be content negotiation or/and format GET variable.

like image 30
Bogdan Kuštan Avatar answered Oct 19 '22 23:10

Bogdan Kuštan