PAYATHON 2026

Slim 4 中如何为不同路由注入不同的服务参数?

数据小许

结论

$internal 的值由具体路由决定,是创建 UserService 时传入的运行配置。自动装配无法判断它应该是 true 还是 false。控制器可以注入 UserServiceFactory,再由对应的方法传入这个值。如果两种模式对应不同的业务用例,也可以拆成不同的方法或服务,避免用布尔参数表达业务含义。

推荐做法:注入工厂

工厂负责创建服务,并复用容器提供的 UserModel。控制器方法根据路由明确传入配置:

class UserServiceFactory
{
    public function __construct(private UserModel $userModel)
    {
    }

    public function create(bool $internal): UserService
    {
        return new UserService($this->userModel, $internal);
    }
}

控制器注入工厂。这样,同一个预先配置的 UserService 实例就不必同时处理两种模式:

class UserController
{
    public function __construct(
        private UserServiceFactory $userServiceFactory
    ) {
    }

    public function getEmployee(
        ServerRequestInterface $request,
        ResponseInterface $response
    ): ResponseInterface {
        $userService = $this->userServiceFactory->create(true);

        // 使用 $userService 处理 employee 请求。
        return $response;
    }

    public function getApplyant(
        ServerRequestInterface $request,
        ResponseInterface $response
    ): ResponseInterface {
        $userService = $this->userServiceFactory->create(false);

        // 使用 $userService 处理 applyant 请求。
        return $response;
    }
}

容器可以自动装配工厂,也可以提供 UserModel 及其所需的 \PDO。\PDO 的具体注册方式和控制器路由的解析方式,取决于项目使用的 PHP-DI 配置和 Slim 集成方式。

考虑改用能表达业务含义的接口

如果 internal 决定了不同的业务行为,提供两个含义明确的方法通常更易读,也能减少调用时传错参数的情况:

class UserService
{
    public function __construct(private UserModel $userModel)
    {
    }

    public function getEmployee(int $id): mixed
    {
        // 执行 employee 场景的处理。
    }

    public function getApplyant(int $id): mixed
    {
        // 执行 applyant 场景的处理。
    }
}

这里的 mixed 只是示意类型,应根据实际返回值替换。控制器可以注入同一个 UserService,再调用对应的方法,无需为每个请求创建带不同布尔值的实例。如果两种场景差异较大,也可以拆成两个服务。

PHP-DI 配置与测试

容器定义适合提供应用范围内固定的依赖,例如数据库连接和模型。路由每次调用时才确定的值,则由调用方或工厂传入。如果确实需要两个长期固定的服务实例,也可以分别在容器中注册并注入,但要明确设置各自的 $internal 值,并让控制器能够区分它们。

测试可以分别覆盖控制器选择场景的逻辑,以及工厂创建服务时是否传入了正确配置。UserModel 依赖 \PDO 时,可以在模型测试中替换数据库依赖。如果直接依赖具体的 \PDO 不便于测试替身,可以考虑在数据访问边界引入接口,再测试依赖该接口的逻辑。

检查类定义

问题中的代码片段有几处类型或属性声明需要修正,否则可能出现 PHP 语法或属性访问问题:

class UserService
{
    public UserModel $user_model;
    public bool $internal;

    public function __construct(UserModel $user_model, bool $internal)
    {
        $this->user_model = $user_model;
        $this->internal = $internal;
    }
}

原片段中的 public UserModel = $user_model; 不是有效的属性声明。$internal 的构造参数类型是 bool,对应的属性也宜声明为 bool。UserModel 示例把依赖赋给了 $this->pdo,但声明的是 $db,两者需要统一,例如:

class UserModel
{
    private \PDO $db;

    public function __construct(\PDO $db)
    {
        $this->db = $db;
    }
}

以上示例展示的是依赖传递方式。具体路由可调用的控制器格式,还需与项目配置的 Slim callable resolver 相匹配。

备注:内容仅供参考。