PDO使用准备好的子查询准备了声明

时间:2017-09-17 20:27:47

标签: php sql pdo subquery prepared-statement

有一个以不同方法准备的复杂查询。这是一个伪代码(不是实际代码):它将在一个方法中准备一个查询,然后在另一个方法中准备一个子查询。

这个想法是其他方法可以添加一些其他查询部分,添加一些条件,并可能添加到其他表的一些连接。并且所有子查询都将以他们的方法准备。

最后,生成的查询将以原始方法执行。

class{//pseudo code

public function getData($name,$club){
  $pdo = new PDO($dsn, $user, $pass, $opt);
  $stm1 = $pdo->query('SELECT name FROM users WHERE quote=?');
  $stm1 = $pdo->prepare('1');

  $stm2 = $this->getQueryPart();
  $stm1->statementBind($stm2);
  $stm1->execute();

  return $query;
}
protected function getQueryPart(){
  $pdo = new PDO($dsn, $user, $pass, $opt);
  $pdo->prepare('AND email = ? AND status=?', ['email@foobar.com','1']);
  return $pdo;
}

1 个答案:

答案 0 :(得分:1)

仅使用PDO是不可能的。您必须创建一个查询构建器类(或使用其中许多现有的类之一)包装PDO ,它将包含所有查询的属性,并构建在执行之前,一次性完成查询。

以下是这将如何运作的基本示例:

ng-if="user.department.id == 1"

通过这门课,你可以做一些这样的事情:

class Query {
    private $select;
    private $from;
    private $where = [];

    /**
     * Defines the column list (SELECT {$columns})
     *
     * @param string $columns
     * @return this
     */
    public function select($columns) {
        $this->select = $columns;
        return $this;
    }

    /**
     * Defines the table to select from (SELECT * FROM {$table})
     *
     * @param string $table
     * @return this
     */
    public function from($table) {
        $this->from = $table;
        return $this;
    }

    /**
     * List of conditions to AND (key = column, value = value)
     * e.g. $query->where(['name' => 'bob'])
     *
     * @param mixed[string] $conditions
     * @return $this
     */
    public function where(array $conditions) {
        $this->where = $conditions;
        return $this;
    }

    /**
     * Adds an AND condition
     *
     * @param string $column
     * @param mixed $value
     * @return this
     */
    public function where_and($column, $value) {
        $this->where[$column] = $value;
        return $this;
    }

    /**
     * Builds and executes the query, returning a PDOStatement
     *
     * @return PDOStatement
     */
    public function execute() {
        $query = sprintf(
            'SELECT %s FROM %s',
            $this->select,
            $this->from
        );

        $placeholders = array();

        if (!empty($this->where)) {
            $query .= ' WHERE ';

            $index = 0;
            foreach ($this->where as $column => $value) {
                if ($index > 0) {
                    $query .= ' AND ';
                }

                $query .= sprintf('`%s`', $column);

                if ($value === null) {
                    $query .= ' IS NULL';
                } else {
                    $placeholder = sprintf(':placeholder_%d', $index);

                    $query .= ' = ' . $placeholder;
                    $placeholders[$placeholder] = $value;
                }

                $index++;
            }
        }

        $pdo = new PDO($dsn, $user, $pass, $opt);
        $stmt = $pdo->prepare($query);
        $stmt->execute($placeholders);
        return $stmt;
    }
}

请参阅此处查看未实际执行查询的示例,但打印将执行的查询和占位符:https://3v4l.org/iKu2K

请注意,这是一个非常基本的示例,只是为了让您了解如何做这样的事情。在实际情况中,您可能希望使用class MyClass { public function getData($name, $club) { $query = new Query(); $query->select('name') ->from('users') ->where(['quote' => '1']); $this->getQueryPart($query); $result = $query->execute(); return $result->fetchAll(PDO::FETCH_ASSOC); } protected function getQueryPart($query) { $query->where_and('email', 'email@foobar.com') ->where_and('status', 1); } } - 条件以及ORLIKE检查的功能扩展此功能,甚至可以对分组条件进行扩展,以便您可以执行某些操作比如!=。更不用说添加对WHERE a = 1 AND (b = 2 OR c = 5)JOINORDER BY和其他奇特内容的支持。