skip to Main Content

I’m looking to structure my Laravel application to efficiently handle both API and view functionalities while avoiding duplication in controllers.

How can I set up my application to have two separate controllers, one dedicated to API actions and the other to view-related actions?

Additionally, what’s the best way to handle shared logic between these controllers, and how can I ensure proper separation of concerns?

2

Answers


  1. You can make same class name that can be used both for API and views. By making controller in different namespaces, e.g.

     // if you try this
     php artisan make:controller API/AuthController
     // it will create controller class along with API folder.
     Http/Controllers/API/AuthContoller.php 
    

    For shared concerns, create Traits folder in app, then create PHP trait class.

    <?php
    namespace AppTraits;
    use AppModelsStudent;
    
    trait StudentTrait {
        public function listAll() {
           // get students
           $students = Student::all();
           return $students; 
        }
    }
    

    You can use it either in your model or controller with use.

    <?php
    namespace AppHttpControllersAPI;
    use IlluminateHttpRequest;
    use AppTraitsStudentTrait;
    
    class AuthController extends Controller
    {
      use StudentTrait;
    
      // do your stuff
    
     public function getStudents(){
        $strudents = $this->listAll();
        return new JsonResponse(['students' => $students, 'msg' => 'success']);
     }
    }
    

    For isolated concerns and structured development, you can create service or repository patterns.
    For more information, follow.

    Login or Signup to reply.
  2. To achieve this, you have to move your logic of your controllers to a separated class/repository than you can call it from your controllers api/web (web is the controllers which you use views), to have a clean structure in your controllers create two folders api and web to separate your controllers (although you can create one controller and not two, i’ll explain this at the end).

    Example

    let’s take an example where you need to show the lists of posts to your user:

    • create PostsRepository:
    AppRepositoriesPostsRepository.php :
    <?php
    
    namespace AppRepositories;
    
    use IlluminateFoundationApplication;
    
    class PostsRepository
    {
        ...
    
        public function getUserPosts() {
            $user = auth()->user();
            $posts = $user->posts()->get()->toArray();
            //do some edits operations on the array
            return $posts;
        }
    }
    

    now in your controllers (web,api) :

    AppHttpControllersWebPostController.php :
    <?php
    
    namespace AppHttpControllersWeb;
    
    use AppHttpControllersController;
    use IlluminateHttpRequest;
    use AppRepositoriesPostsRepository;
    
    class PostController extends Controller
    {
        public function getPosts(Request $request, PostsRepository $postsRepository)
        {
            $postsList = $postsRepository->getUserPosts();
    
            return view('main.posts', compact('postsList'));
        }
    }
    

    and in the api controller :

    AppHttpControllersApiPostController.php :
    <?php
    
    namespace AppHttpControllersApi;
    
    use AppHttpControllersController;
    use IlluminateHttpRequest;
    use AppRepositoriesPostsRepository;
    
    class PostController extends Controller
    {
        public function getPosts(Request $request, PostsRepository $postsRepository)
        {
            $postsList = $postsRepository->getUserPosts();
    
            return response()->json([
                ...
                'postsList' => $postsList
            ]);
        }
    }
    

    this way, you can separate the data delivery to user (api or web) but still have one source of data ($postsRepository->getUserPosts()) so you avoided duplication.

    Even though, you can use one controller for both Api and Web :

    you can the wantsJson methods for example :

    AppHttpControllersPostController.php :
        <?php
    
    namespace AppHttpControllers;
    
    use AppHttpControllersController;
    use IlluminateHttpRequest;
    use AppRepositoriesPostsRepository;
    
    class PostController extends Controller
    {
        public function getPosts(Request $request, PostsRepository $postsRepository)
        {
            $postsList = $postsRepository->getUserPosts();
    
            if ($request->wantsJson()) {
                //means that the client is from api
                return response()->json([
                    ...
                    'postsList' => $postsList
                ]);
            }
            else{
                //means that the client is from web
                return view('main.posts', compact('postsList'));
            }
        }
    }
    

    And for the api clients add this header to their requets:

    "Accept: application/json"
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search