Slim框架父控制器容器复用问题及优化方案咨询
Slim框架控制器复用容器与避免重复代码的解决方案
我在使用Slim框架开发项目,现有HomeController继承自Controller类,代码可正常运行。为避免在每个控制器中重复编写构造代码,希望将HomeController构造函数中获取container、db、view的逻辑移至父Controller类,以便直接像访问$this->test一样访问$this->view和$this->db。但尝试后发现父类构造函数未执行,调用parent::__construct()时又出现参数不足错误,现寻求可复用容器、避免重复代码的最优实现方式。
原始相关代码
HomeController.php
<?php namespace Controllers; use DI\Container; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Slim\Views\Twig; class HomeController extends Controller{ private $db; private $view; private $container; public function __construct(Container $container){ $this->container = $container; $this->db = $container->get('db'); $this->view = $container->get('view'); } public function index(Request $request, Response $response, $args){ echo $this->test; // 'hello world'; This is from Controller.php echo $this->container->get('container-test'); // I am from container is the string i pass is container and i am getting output. echo $this->container_from_controller?'Captured':'Not Captured'; // Not Captured i.e the container in Controller.php is empty return $this->view->render($response, 'home/index.html', [ 'name' => 'from home controller' ]); } }
Controller.php
<?php namespace Controllers; use DI\Container; class Controller{ protected $container_from_controller; protected $test = 'hello world'; public function __construct(Container $container){ $this->container_from_controller = $container; } }
composer.json
{ "require": { "slim/slim": "4.*", "slim/psr7": "^1.6", "php-di/slim-bridge": "^3.4", "dcblogdev/pdo-wrapper": "^2.0", "slim/twig-view": "^3.3" }, "autoload": { "psr-4": { "Controllers\\": "src/Controllers" } } }
问题原因
- 父类构造函数未自动执行:当子类定义了自己的构造函数时,PHP不会自动调用父类的构造函数,必须显式调用
parent::__construct()才能触发父类构造逻辑。 - 参数不足错误:子类构造函数接收
Container参数,但调用parent::__construct()时未传递该参数,导致父类构造函数因缺少必要参数而报错。
最优实现方案
将父类改为抽象基类BaseController,在基类构造函数中统一处理容器依赖的注入与资源获取,子类无需编写构造函数,直接继承基类即可使用已初始化的$this->db和$this->view。
修改后的BaseController.php
<?php namespace Controllers; use DI\Container; abstract class BaseController{ protected $db; protected $view; public function __construct(Container $container){ $this->db = $container->get('db'); $this->view = $container->get('view'); } }
修改后的HomeController.php
<?php namespace Controllers; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; class HomeController extends BaseController{ public function index(Request $request, Response $response, $args){ $sql = "SELECT * FROM list"; $rows = $this->db->rows($sql); var_dump($rows); return $this->view->render($response, 'home/index.html', [ 'name' => 'from home controller' ]); } }
方案说明
- 抽象基类
BaseController确保所有子类共享同一套资源初始化逻辑,避免重复代码。 - PHP-DI容器会自动将
Container实例注入基类的构造函数,子类无需手动处理参数传递。 - 子类直接通过
$this->db和$this->view访问资源,代码更简洁,可维护性更强。
内容的提问来源于stack exchange,提问作者Alaksandar Jesus Gene
相关产品推荐
相关产品推荐

