控制器在清洁架构中

时间:2016-11-30 10:18:50

标签: controller clean-architecture dependency-rule

我试图在Laravel应用程序中应用Bob叔叔的Clean Architecture

我所关注的是:正如鲍勃叔叔所描述的那样,控制器应该属于第三个圈子:接口适配器(从里到外)。这意味着Controller仅依赖于Use Case Circle(2nd),并且不应该对第4圈中的框架有任何了解。

但是某些框架中的控制器必须扩展基类(例如,一个AbstractController类),它还需要接收一个Request对象,有时还会返回一个Response对象,所以这种打破了依赖规则

我误解了吗?如果没有,是否有任何解决方案不打破依赖规则

我的控制器看起来像这样:

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use User\UseCase\FetchUsers;
use User\UseCase\FetchUsersRequest;

class UserController extends Controller
{
    public function index(Request $request, FetchUsers $fetchUsersUseCase)
    {
        $useCaseRequest = new FetchUsersRequest(
            // extract data from Request
        );

        $useCaseResponse = $fetchUsersUseCase->handle($useCaseRequest);

        return [
            'users' => $useCaseResponse->users,
        ];
    }
}

2 个答案:

答案 0 :(得分:1)

AbstractController属于第三个圈。所以你不要打破任何依赖。如果您在用例圈中有数据传输对象(DTO),以便将数据传输到第三个圈,那么您就不会破坏任何依赖。

为了实现这一目标,您应该为所有请求和响应创建DTO,将您的实体映射到DTO并共享DTO而不是实体。

例如:您有一个User实体,其字符串变量名为Name。您有一个控制器将从use-cases圈中获取用户。

解决方案:使用字符串变量创建名为UserDto的DTO(您可以将其称为Name)。 Controller知道UserDto但不知道User entity

答案 1 :(得分:0)

有点太晚了,但您可以在用例圈中创建一个特定控制器的接口(这将在干净架构中称为输入端口)。

然后,您可以在第三个圆圈中实现界面,例如

// In the use-cases circle
interface UserControllerInterface(){

    public function index(Request $request, FetchUsers $fetchUsersUseCase);

}

// In the third circle
class UserController extends Controller implements UserControllerInterface{

    public function index(Request $request, FetchUsers $fetchUsersUseCase){
        $useCaseRequest = new FetchUsersRequest(
            // extract data from Request
        );

        $useCaseResponse = $fetchUsersUseCase->handle($useCaseRequest);

        return [
            'users' => $useCaseResponse->users,
        ];
    }
}

这样你就不会违反纪律。