我有相同的大块代码while循环,其条件需要fetch_assoc()在MySqli连接上,但fetch()在PDO连接上。我想删除两次包含相同代码块的冗余。写成长格式,它的形状是:
if ($connection_type == 'mysqli')
while ($row = $resultObject->fetch_assoc()) {
[big routine]
}
} elseif ($connection_type == 'pdo') {
while ($row = $resultObject->fetch()) {
[same big routine]
}
}
我发现我可以,事实上,组合条件,但只是因为我目前只有2种连接可能性(MySqli和PDO),所以这不是理想的,如果-不知怎的-我希望在未来使用第三个连接条件:
while (($connection_type == 'mysqli') ? $row = $resultObject->fetch_assoc() : $row = $resultObject->fetch()) {
[big routine]
}
有更有效的方法吗?这个解决方案是否存在不明显的缺陷?如果涉及超过2种不同的连接条件,该怎么办呢(显然,我在这里展望未来)
在我看来,处理这个问题最简单的方法是抽象掉两个api之间的差异。
例如:
<?php
interface DBResult {
public function fetch();
}
class MysqliDbResult implements DBResult {
private $stmt;
public function __construct(mysqli_stmt $stmt){
$this->stmt = $stmt;
}
public function fetch(){
return $this->stmt->fetch_assoc();
}
}
class PdoDbResult implements DBResult {
private $stmt;
public function __construct(PDOStatement $stmt){
$this->stmt = $stmt;
}
public function fetch(){
return $this->stmt->fetch('PDO::FETCH_ASSOC);
}
}
当您从数据库连接实例化一个新类型的结果时,您可以将其包装在适当的DBResult实现中。
// is resultObject pdo or mysqli .... I don't care ...
while ($row = $resultObject->fetch()) {
[same big routine]
}
这听起来像是适配器模式的完美用例。您将创建一个具有fetch方法的类,该方法的作用类似于内部mysqli或PDO实例的适配器。您也可以一次性地对函数执行此操作。
function fetch($resultObject, $connection_type) {
switch ($connection_type) {
case 'mysqli':
return $resultObject->fetch_assoc();
case 'pdo':
return $resultObject->fetch();
case '....':
//more cases
}
}
while ($row = fetch($resultObject, $connection_type)) {
big_routine($row);
}