在PDO中处理可更改查询的正确方法?

时间:2015-03-26 21:30:46

标签: php mysql pdo

我目前正在建立一个新闻网站,其中包含发布内容,将内容标记为类别和投票等功能。

我已经到了为我的用户制作主页的阶段,这将显示最新的帖子,但我想让我的用户能够按类别排序。

这是我当前的查询

SELECT p.*, 
             (SELECT Count(id) 
                    FROM   comments AS c 
                    WHERE  c.post = p.id) AS commentCount,
                    v.type AS vote_type,
             (SELECT Count(id) 
                    FROM   votes AS vo
                    WHERE  vo.post_id = p.id) AS totalVotes
FROM   posts AS p
LEFT JOIN tagged AS t 
            ON p.id = t.post_id
LEFT JOIN votes AS v
            ON v.post_id = p.id
    WHERE (v.user_id = 1 OR v.user_id IS NULL)
    AND t.tag_id = 7
ORDER BY timestamp DESC
LIMIT :limit OFFSET :offset

此查询具有以下代码部分,使其返回仅分配(标记)类别ID为7的帖子(如果没有这两部分,查询将成为我通常用于最新的基本查询职位)

LEFT JOIN tagged AS t ON p.id = t.post_id

AND t.tag_id = 7

我想知道是否有办法让基本查询没有类别代码,然后如果需要输入类别代码而不是有两个查询?有没有办法让查询“动态”。

我想实现其他排序功能,但是觉得创建一堆(稍微)不同的副本会效率低下。

1 个答案:

答案 0 :(得分:1)

是的,人们总是这样做。您可以动态设置参数,例如在下面的第一个示例中,也可以动态构建SQL语句。我认为最佳做法是:1。确保它不会变得太复杂。如果您的查询对每个人都是一切,请查看构建查询构建器或多个查询。 2.将动态SQL语句与动态参数组合。

准备你的陈述:

SELECT p.*, 
             (SELECT Count(id) 
                    FROM   comments AS c 
                    WHERE  c.post = p.id) AS commentCount,
                    v.type AS vote_type,
             (SELECT Count(id) 
                    FROM   votes AS vo
                    WHERE  vo.post_id = p.id) AS totalVotes
FROM   posts AS p
LEFT JOIN tagged AS t 
            ON p.id = t.post_id
LEFT JOIN votes AS v
            ON v.post_id = p.id
    WHERE (v.user_id = 1 OR v.user_id IS NULL)
    AND t.tag_id = :tagid
ORDER BY timestamp DESC
LIMIT :limit OFFSET :offset

现在绑定你的元素(伪代码):

if( ! isset( $someValue ) ) $someValue = 7; // I am just giving it a default value for 
// an example.  You can do whatever.
pdo->bindParam( ':tagid', $someValue, parameterType such as PDO::PARAM_INT);

您可以继续这样构建,或者您可以分解更大的SQL准备语句。举例来说:

if( $categoryCodeNeeded === true ) // add another and statement to where portion of your sql statement
  $select += " AND tag_id = 7 ";

编辑以回答评论中的问题:

您提供的代码:SELECT p。*现在分配给变量,或者在另一段代码中,如下所示:

$statement = $dbHandler->prepare('SELECT p.* FROM posts p blah blah blah' ); 

如果是第二种情况,那么您可以将该行代码更改为:

$ statement = $ dbHandler-> prepare($ yourOwnSelectVariable);

然后,您可以根据需要构建变量。

$yourOwnSelectVariable = "SELECT p.* FROM posts p";
if( $categoryCodeNeeded )
    $yourOwnSelectVariable += " WHERE tag_id = :tagid ";
$statement = $dbHandler->prepare( $yourOwnSelectVariable );
if( ! isset( $tagId ) ) $tagId = 7;
    $statement->bindParam( ':tagid', $tagId, PDO::PARAM_INT);