I'll-Be-Back
I'll-Be-Back

Reputation: 10828

API Internal requests on own website?

I want to develop a website and an App for Android and Apple. An App will fetch the data via API from our domain.

Let say on our website, it will show a list of products or create user account; In the controller, I could use internal API request which will then fetch the data via MySQL rather than using MySQL query method directly on it own. Is this common practice or bad practice?

This is example of dingo/api internal request (Laravel):

Route::api(['version' => 'v1', 'prefix' => 'api'], function () {

    Route::get('users', function () {
        // fetch from database
        return User:all();
        });
});

In the Controller

class UsersController
{

    public function showUsers()
    {
        $users = API::get('users');

        return View::make('users-list')->with('users', $users);
    }
}

In this example they have an API route setup for get method at users and API::get('users'); will make an internal request to that end point and return you what ever that method returns

Upvotes: 2

Views: 1584

Answers (1)

lukasgeiter
lukasgeiter

Reputation: 152900

Yes I would consider this common practice. I personally even think it's good practice to consume your own API internally. It definitely helps keeping your code DRY (Dont Repeat Yourself).

Of course it causes a bit of an overhead compared to a direct method call, but I doubt it will be noticeable. Anyways, for your consideration, an alternative would be to keep the API controllers very very flat and have most of your logic somewhere else (in the Model, a Repository or a Service Layer). I recommend doing that anyways. This would mean that you could easily do the same thing in your in your "normal" controller as you do in the API controller because it's basically just a (few) call(s) to another class.

Here's an example to illustrate what I mean

Let's say your users endpoint is a bit more complicated (This includes some eager loading and filtering)

public function index(){
    return User::has('profile')
               ->with('profile', 'city')
               ->active()
               ->get();
}

Now of course it still isn't a lot of code and you could easily do the same in the other controller as well. But imagine you wanted to add a new relationship to eager load. You would need to change your code in two places. (If you would forget one you probably wouldn't even notice it...)

One solution to this problem is creating a repository. I won't go into the details on how to implement this pattern (there are a lot resources about this on the internet) but basically in the end you'd have a class like this:

class UserRepository {
    public function getAll(){
        return User::has('profile')
               ->with('profile', 'city')
               ->active()
               ->get();
    }
}

(Ideally you would also have an interface defining your repository...)

Then use dependency injection to make an instance of the class available in your controller: (Again this is not complete you'd need a few more things to set up DI)

public function __construct(UserRepository $repo){
    $this->user = $repo;
}

public function index(){
    return $this->user->getAll();
}

And in your other controller(s) you could use the exact same call getAll().

Upvotes: 6

Related Questions