PHP多控制器类重复方法的最优OOP实现方案咨询
嘿,我来帮你搞定这个代码重复的问题!你现在遇到的确实是OOP里典型的“坏味道”——重复代码,不仅维护麻烦,改一处要改N个地方。好在你的两个控制器都继承了baseController,把重复的方法移到父类里绝对是当前场景下的最优解,既贴合现有架构,改动量也最小,完全符合DRY(Don't Repeat Yourself)原则。
具体实现步骤
1. 改造父类baseController
把两个子类里重复的getResultAndCount方法移到父类中,注意要把方法权限改成protected(这样子类才能调用),同时确保父类能访问到子类的$table属性:
<?php namespace controller; class baseController { // 假设父类原本就有这些公共属性(比如PDO实例、Twig引擎) protected $pdo; protected $twig; // 抽离后的公共方法 protected function getResultAndCount() { $sql = 'SELECT * FROM ' . $this->table; // 注意:这里要确保先执行查询再获取行数(如果你的PDO封装需要的话) $this->pdo->query($sql); $count = $this->pdo->rowCount(); $rows = $this->pdo->resultset(); return [$rows, $count]; // 用短数组语法更简洁 } }
2. 修改子类控制器
把子类里的$table属性权限从private改成protected(这样父类方法能读取到),然后删掉子类自己的getResultAndCount方法:
accountController修改后:
<?php namespace controller\admin; class accountController extends \controller\baseController { // 把private改成protected,让父类能访问 protected $table = 'account'; public function itemslist() { list($res, $totalcount) = $this->getResultAndCount(); return $this->twig->render('/admin/accounts.html.twig'); } // 保留其他自定义方法,删除重复的getResultAndCount // ... other methods ... }
userController修改后:
<?php namespace controller\admin; class userController extends \controller\baseController { protected $table = 'user'; public function itemslist() { list($res, $totalcount) = $this->getResultAndCount(); return $this->twig->render('/admin/users.html.twig'); } // ... other methods ... }
为什么这是最优解?
- 最小改动:完全利用现有继承关系,不需要新增类、接口或依赖,代码侵入性极低
- 易维护:以后要修改
getResultAndCount的逻辑,只需要改父类这一处,所有子类自动生效 - 扩展性强:后续新增其他控制器(比如
orderController),只要继承baseController并设置protected $table,就能直接复用这个方法
额外注意点
- 属性权限的坑:一定要把子类的
$table从private改成protected,否则父类方法无法读取子类的私有属性,会直接报错。 - rowCount()的兼容性:部分数据库驱动(比如PostgreSQL)对SELECT语句的
rowCount()支持不佳,更可靠的方式是单独执行COUNT(*)查询,示例如下:
protected function getResultAndCount() { // 先查询总数 $countSql = "SELECT COUNT(*) FROM {$this->table}"; $count = $this->pdo->single($countSql); // 假设你的PDO封装有single方法返回单个值 // 再查询数据 $dataSql = "SELECT * FROM {$this->table}"; $rows = $this->pdo->resultset($dataSql); return [$rows, $count]; }
对比其他方案的优劣
- 独立工具类:比如写一个
DataHelper静态类调用,需要传递$pdo和$table参数,破坏了控制器的封装性,不如继承方式简洁。 - 接口:接口只能定义方法签名,不能实现逻辑,反而需要每个子类重复写实现,完全解决不了代码重复的问题,不适合当前场景。
内容的提问来源于stack exchange,提问作者Carlos
相关产品推荐
相关产品推荐

