Laravel/PHP中如何让ApiController子类自动注入对应Repository
解决方案
我们可以通过PHP反射机制结合依赖注入容器(以Laravel容器为例,其他框架可替换为对应实现)来实现需求,让所有继承ApiController的子类自动注入对应Repository,无需重复编写构造逻辑。
步骤1:重构父类ApiController
use ReflectionClass; use Illuminate\Container\Container; class ApiController { public function __construct() { // 获取当前子类的反射实例 $reflection = new ReflectionClass($this); // 提取控制器短类名(如 AddressController) $controllerShortName = $reflection->getShortName(); // 推导对应Repository类名:去掉Controller后缀,拼接Repository $repositoryShortName = str_replace('Controller', 'Repository', $controllerShortName); // 拼接Repository完整命名空间(请根据你的项目实际命名空间调整) $repositoryFullClass = "App\\Repositories\\{$repositoryShortName}"; // 从容器中解析Repository实例(框架容器会自动处理其内部依赖) $repositoryInstance = Container::getInstance()->make($repositoryFullClass); // 推导属性名:Repository类名转为小驼峰(如 addressRepository) $propertyName = lcfirst($repositoryShortName); // 检查子类是否声明了对应属性,若存在则赋值 if ($reflection->hasProperty($propertyName)) { $property = $reflection->getProperty($propertyName); $property->setAccessible(true); // 允许访问私有属性 $property->setValue($this, $repositoryInstance); } } }
步骤2:简化子类控制器
现在子类仅需声明对应的Repository属性,无需编写构造函数:
class AddressController extends ApiController { private AddressRepository $addressRepository; // 业务逻辑方法编写... }
class CountyController extends ApiController { private CountyRepository $countyRepository; // 业务逻辑方法编写... }
核心说明
- 命名规则约束:方案依赖固定命名规则:控制器类名必须以
Controller结尾,Repository类名需对应去掉Controller后缀并加上Repository,属性名采用Repository类名的小驼峰形式。 - 容器适配:示例使用Laravel容器,若为Symfony等其他框架,替换为对应框架的容器获取方式即可;若无框架容器,可直接用
new $repositoryFullClass()实例化,但需自行处理Repository的依赖注入。 - 私有属性赋值:通过反射的
setAccessible(true)实现对私有属性的赋值,保证代码符合封装规范的同时完成自动注入。
内容的提问来源于stack exchange,提问作者oussama benounnas
相关产品推荐
相关产品推荐

