Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Ady_Gould's avatar

Servicing an API and Web UI from same Laravel installation

A fellow educator and I are wondering the best way to deal with a situation of having a Web UI and API being hosted from the same installation instance of Laravel.

We have a problem where we need an API to be served to a mobile application (to be developed), with tokens, etc, for security, plus a web UI for access from the desktop and browsers, for the administration of the application, and for general users to access the site when not on their phone/tablet.

We would like to know what the best ways are to:

  • use the same code base as much as possible
  • avoid problems of code reproduction
  • allow routes to be as similar as possible (just with API added as needed)
  • reduce the overhead of writing and maintaining code across two different instances of Laravel

We have thought of the likes of:

  • capturing the request and checking to see if it is an API call
  • Creating API controllers separate from the UI controllers
  • Making the Models 'heavy'

Is anyone able to give some guidance on the best way to structure and then implement this form of situation, and possibly a small example of a solution?

Many thanks in advance. Ady

0 likes
8 replies
jlrdw's avatar

Well the web based is self explanatory, I would consider passport for the token based api.

See https://www.sitepoint.com/php-authorization-jwt-json-web-tokens/

Also some hosting like digital ocean and AWS actually have tutorials. Also verify you need it as an API, perhaps just doing a mobile friendly responsive would work, depending on the expected traffic.

1 like
Ady_Gould's avatar

@jlrdw thank you for the advice...

In this case, we need an API - or to be more precise, the students have to create an API as part of their assessable items.

We combine this with their Mobile App development so they consume the API when they implement the native app for mobile devices.

martinbean's avatar

@ady_gould There are two layers here: requests coming into your application handled by controllers; these controllers then delegate to the “business logic” layer, i.e. your models.

If you have separate controllers for “web” requests and API requests (which you should) then these controllers can call on the same models. To reduce duplication, you can wrap operations up into “service” classes. These are just classes that have methods to execute domain logic. You can re-use the same service classes in both your “web” and API controllers.

For your “web” routes, you can use the out-of-the-box, session-based authentication. For your API routes, you can use something like Passport to enable token-based authentication for your mobile apps.

Don’t try and re-use controllers for “web” and API requests. They’re two separate entry points into your application. Changes to your API shouldn’t mean changes to your “web” front-end, and changes to your “web” front-end shouldn’t mean you need to change your API. Once you roll out API endpoints, you have to assume they’re being consumed immediately. So any changes to an API endpoint, or request or response format is going to break—and incur work—for any client using those API endpoints. Your “web” front-end, you’re a lot more flexible to make changes as needed.

1 like
Ady_Gould's avatar

@martinbean thank you for the explanation.

The joy of being an educator (primarily) is that I often don't get to spend enough time developing code, so your explanation helps a great deal.

I'm used to doing the web front end + back end combined, but this need for API as well had myself, and my colleague debating best practice.

From my understanding, we put the majority of the logic in the model, returning results to both the API and WEB controllers that then handle how the data is then presented to their respective destinations.

This makes the models 'heavy' and the controllers 'light'.

The controllers could then handle the respective methods to validate requests etc.

With this in mind, creating controllers with names such as ProductsApiController and ProductsController would allow the two to be separate but relatively easy to maintain.

As for the API changes, we are attempting to have the students (and ourselves) understand how to implement APIs, so we are in a luxury situation that changes to the API are not going to affect the clients at this point and the students are very much in charge of both ends of the API loop.

Once again thanks.

martinbean's avatar
Level 80

From my understanding, we put the majority of the logic in the model, returning results to both the API and WEB controllers that then handle how the data is then presented to their respective destinations.

@ady_gould Yeah, pretty much. If you can keep as much logic in models and services classes, then your controllers end up being “marshals” that take a HTTP request, call the relevant domain logic, and then present the results (whether that be in a Blade template or as a JSON/XML response or whatever).

So if you have an API endpoint to create a post, as well as the ability to create a post from the “web” front-end, then the respective controllers could call on the same service method to accomplish that:

namespace App\Http\Controllers;

class PostController extends Controller
{
    protected $postService;

    public function __construct(PostService $postService)
    {
        $this->postService = $postService;
    }

    public function store(StoreArticleRequest $request)
    {
        $post = $this->postService->create($request->validated());

        return redirect('/posts')->with('success', 'Post was created.');
    }
}
namespace App\Http\Controllers\Api;

class PostController extends Controller
{
    protected $postService;

    public function __construct(PostService $postService)
    {
        $this->postService = $postService;
    }

    public function store(StoreArticleRequest $request)
    {
        $post = $this->postService->create($request->validated());

        return new JsonResponse($post, 201);
    }
}

So both controllers call on the same class and method to create a post, but return different responses depending on if it’s the “web” controller or the API controller. This means that if you need to change how a post is created, you only need to do that in one place (the PostService class).

With this in mind, creating controllers with names such as ProductsApiController and ProductsController would allow the two to be separate but relatively easy to maintain.

I tend to namespace controllers. So above you’ll see I put the API controller in its own sub-namespace (App\Http\Controllers\Api) so that API controllers are separated from the “web” controllers. I’ll do the same for controllers for things like admin panels or whatnot. But this is just personally preference.

2 likes
Ady_Gould's avatar

@martinbean, Huge thank you!

Your explanations have been great! I do agree that using 'namespacing' is the better option.

I'm going to ask one more question based on your examples: The PostService contains what would be the traditional controller components... minus the response methods...

I found this article: https://blackdeerdev.com/laravel-services-pattern/ which matches that idea.

martinbean's avatar

@ady_gould No problem. Glad I was able to help :)

Yeah, that blog post has pretty much an example of what I was trying to get across. Basically just extracting the business logic from your controller actions, to another class that can then be re-used in multiple places.

1 like
Ady_Gould's avatar

Cheers @martinbean

Many thanks again, you've been superb in your explanations and taking the time to step through the process.

I'm giving you multiple 👍

Please or to participate in this conversation.