在PDO中使用动态预处理语句

时间:2012-04-05 23:20:08

标签: php coding-style pdo

有时,根据查看我的页面的用户类型,我需要添加一个JOIN,甚至只是限制结果。是否有更清洁的方式去做?我应该为每种类型的请求单独声明吗?什么更“适当”?

以下是我的代码最终看起来像:

// Prepare statement
$stmt = $this->db->prepare('
    SELECT *
    FROM    Documents
    LEFT JOIN Notes ON ID = D_ID
    '.($user_id ? "INNER JOIN Users ON UID = ID AND UID = :userid" : '')."
    ". ($limit ? 'LIMIT :offset, :limit' : '')
);

// Bind optional paramaters
if ($user_id) $stmt->bindParam(':userid', $user_id, DB::PARAM_INT);

if ($limit)
{
    $stmt->bindParam(':offset', $limit[0], DB::PARAM_INT);
    $stmt->bindParam(':limit', $limit[1], DB::PARAM_INT);
}

2 个答案:

答案 0 :(得分:1)

为了清楚起见,可能只需将插入字符串包装到自己的方法中,例如getUserInsertString($user_id),并尝试使引用更加一致。

另外,您是否只是通过$user_id来测试是否定义了$limitif ($user_id)?如果是这样,如果您将错误报告转向所有,则会收到一堆未定义的变量警告。您可能需要考虑使用if (isset($user_id))

答案 1 :(得分:0)

我创建了单独的(受保护的)函数,这些函数返回一个只需要执行的预准备语句。

/**
* @returns PDOStatement
*/
protected function prepareStatementForCase1(PDO $dbObject,Object $dataToBind){...}
/**
* @returns PDOStatement
*/
protected function prepareStatementForCase2(PDO $dbObject,Object $dataToBind){...}

然后,我会在外面决定哪一个必须被调用。 您可以更轻松地重建,维护和阅读代码。

示例:

class Document{
  protected $dbObject;

  public function __construct(PDO $dbObject){
    $this->dbObject=$dbObject;
  }
  public function doQuery($paramOne,$paramTwo,...){
    $logicalFormulaOne=...; // logical expression here with parameters
    $logicalFormulaTwo=...; // logical expression here with parameters
    if($logicalForumlaOne){
      $dbStatement=$this->prepareStatementForCase1($dataToBind);
    }else if($logicalFormuleTwo){
      $dbStatement=$this->prepareStatementForCase2($dataToBind);
    }
    $dbResult=$dbStatement->execute();
  }
  protected function prepareStatementForCase1(Object $dataToBind){
    $dbStatement=$this->dbObject->prepare("query string");
    $dbStatement->bindParam(...);
    return $dbStatement;
  }
}

但是当你的PDOResult对象表示不同类型的数据库元组,或者在其中一个案例中返回更多行时,我不建议这样做。

我通常做的是创建一个代表(在你的例子中)Document的类。只有一个。我可以插入,删除,选择,修改其字段,并处理一个项目。当我需要(例如)获取更多它们时,我创建了一个新类,例如DocumentList,用于处理文档集合。这个类在获取更多文档对象时会给我一个Document对象数组。