Say you have a HomepageController that' suppose to show all the blogs, users, gallery, and some members-only info (for logged-in users)

Normally, it looks like this:

<?php

class HomepageController
{
    public function index()
    {
        $blogService = new BlogService();       
        $data['blogs'] = $blogService->getAll();

        $userService = new UserService();       
        $data['users'] = $userService->getAll();

        $galleryService = new GalleryService();     
        $data['users'] = $userService->getAll();

        $data['membersOnlyInfo'] = [];

        if ($userIsLoggedIn)
        {
            $membersOnlyService = new MembersOnlyService();
            $data['membersOnlyInfo'] = $membersOnlyService->getTopSecretInfo();
        }       

        Render($data);
    }
}

This thing is arguably fat already but it can get more fat at some point in the future. In this case, is it better to wrap this inside in a "Controller Service"? E.g.:

class HomepageService
{
    public function index()
    {
        $blogService = new BlogService();       
        $data['blogs'] = $blogService->getAll();

        $userService = new UserService();       
        $data['users'] = $userService->getAll();

        $galleryService = new GalleryService();     
        $data['users'] = $userService->getAll();

        $data['membersOnlyInfo'] = [];

        if ($userIsLoggedIn)
        {
            $membersOnlyService = new MembersOnlyService();
            $data['membersOnlyInfo'] = $membersOnlyService->getTopSecretInfo();
        }       

        return $data;
    }
}

So that the controller will just look like this:

class HomepageController
{
    public function index()
    {
        $data = new HomepageService();      

        Render($data);
    }
}

There's some logic in the first controller (i.e., if ($userIsLoggedIn)) and since controllers shouldn't have any business logic, I guess this makes sense. Is this a good practice or is it overkill?

Note: For simplicity dependency injection is omitted in this example.

有帮助吗?

解决方案

Yes, its a good idea to have a service layer. Generally your controller should only worry about producing a View from the Model, deserialising inputs etc.

The service layer keeps your business logic separate from the web page and allows for unit tests and reuse in say a mobile or destop app.

In your example its arguable which bits of logic should go in the service and which, if any, should remain in the controller. But you should definitely have a one to one mapping of controller method to service method in most cases.

其他提示

Leave it as it is, it’s not that bad and you can refactor it easily. Maybe put that if statement in to separate class. Go with HomeService if you want to test this logic in isolation from your web framework, or you plan to add web api with the same functionality. Of course there could be some nuances that I missed, since I don’t know PHP :)

EDIT: You could use some dependecy injection

许可以下: CC-BY-SA归因
scroll top