Skip to content

Latest commit

 

History

History
140 lines (110 loc) · 6.11 KB

File metadata and controls

140 lines (110 loc) · 6.11 KB

静态查询

Drupal 7 最常见的查询形式是静态查询,一个静态查询几乎是一字不差的被发送到数据库。只有 Select 查询可以使用静态查询。

只有非常简单的查询应该使用静态查询架构。如果你需要构建复杂的查询,你应该使用动态查询机制,包括动态查询的生成或修改。

静态查询的在内部使用的是一个query方法:

<?php
$result = $conn->query("SELECT nid, title FROM {node}");
?>

不过还是推荐使用面向过程的包装函数:

<?php
$result = db_query("SELECT nid, title FROM {node}");
?>

上面调用 db_query 方法的代码等价于如下代码:

<?php
$result = Database::getConnection()->query("SELECT nid, title FROM {node}");
?>

很容易可以看出为什么推荐包装后的函数了吧!

db_query() 可以接受3个参数。第一个是查询语句,在合适的地方使用占位符,并且使用花括号标识出所有的表名。第二个参数是一个占位符和对应值的关联数组。第三个参数是可选的,是一个配置指令的数组,指出查询怎样被执行。

前缀

在静态查询中,所有的表名必须以花括号({})包围。这样标识可以让数据库系统自动在查询时给表名加上合适的前缀。前缀的方法实现了使用相同的数据库运行多个Drupal站点,或者在少数情况下在不同的站点之间共享表。

占位符

查询中的占位符标记会在执行的时候被替换成真实值。通过将占位符所代表的值与查询分离,我们可以让数据库抽象层对不同数据库引擎的SQL语法和输入值进行区分和处理,因此也避免了SQL注入。

<?php
$result = db_query("SELECT nid, title FROM {node} WHERE created > :created", array(
  ':created' => REQUEST_TIME - 3600,
));
?>

上面的代码可以读取所有一小时内创建的节点。占位符 created 将会在查询被执行时自动地被替换成值 REQUEST_TIME - 3600。一个查询可以有任意数量的占位符,但是所有占位符必须有唯一不重复的命名,即使它们的值是一样的。根据具体情况,占位符数组可以像上面的例子一样写在包装函数里,或者在之前构造好,然后传参数进去。数组元素的顺序没有关系。

db_ 开头的占位符被保留为内部系统所使用,我们不可以显式的使用它们。

注意,不管什么类型的占位符,都不应该被转义或者用引号包围。因为它们被分别的传递到数据库服务器,服务器能够自己区分查询和值。

<?php
// WRONG:
$result = db_query("SELECT nid, title FROM {node} WHERE type = ':type'", array(
  ':type' => 'page',
));
// CORRECT:
$result = db_query("SELECT nid, title FROM {node} WHERE type = :type", array(
  ':type' => 'page',
));
?>

占位符不应该,也不能被用于字段名和表名。如果查询里的表名是来自于不安全的输入,表名需要使用 db_escape_table() 处理后才能用于查询。

占位符数组

Drupal的数据库层包含一个额外的占位符特性。如果为占位符传入的是一个数组,则占位符会自动被扩展成一一对应的逗号分隔的占位符列表,这意味着开发者不需要担心弄错占位符的数量:

<?php
// This code:
db_query("SELECT * FROM {node} WHERE nid IN (:nids)", array(':nids' => array(13, 42, 144));
// Will get turned into this prepared statement equivalent automatically:
db_query("SELECT * FROM {node} WHERE nid IN (:nids_1, :nids_2, :nids_3)", array(
  ':nids_1' => 13,
  ':nids_2' => 42,
  ':nids_3' => 144,
));
// Which is equivalent to the following literal query:
db_query("SELECT * FROM {node} WHERE nid IN (13, 42, 144)");
?>

查询选项

db_query() 的第三个参数(对应连接对象的查询方法)是一个数组,指明了查询将会怎样被执行。典型地,大多数查询只有两个选项。其他的值大多只在内部使用。

target 指出了查询的连接目标。如果没指定,默认指向 default。而另一个值是 slave,指出查询应该在从服务器上执行,如果存在的话。

fetch 指定了查询结果应该如何被返回。合法的值包括:PDO::FETCH_OBJ, PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH,或者是一个类名的字符串。如果是类名字符串被指定,每条返回结果将被以那个类对象的形式被返回。其他所有值的行为都是由PDO定义的,将会以标准类 stdClass 对象,关联数组,数字索引数组以及关联和数字同时返回等方式返回结果。可参考:http://php.net/manual/en/pdostatement.fetch.php。默认值是 PDO::FETCH_OBJ,我们大多用这个默认行为,除非你有特殊的理由才会去选择其他值。

下面的例子将会在从服务器(如果有的话)执行一个查询,并且从结果集中以关联数组的形式返回记录。

<?php
$result = db_query("SELECT nid, title FROM {node}", array(), array(
  'target' => 'slave',
  'fetch' => PDO::FETCH_ASSOC,
));
?>

使用结果集

结果集对象通过调用 db_query() 返回,能够被用于获取结果的每一行以及其数据列的值。在下面的例子中,$result 变量包含了查询返回的所有行,然后里面的每一行被每次一个的通过 fetchAssoc() 取出并赋值给 $row

<?php
  $sql = "SELECT name, quantity FROM goods WHERE vid = :vid";
  $result = db_query($sql, array(':vid' => $vid));
  if ($result) {
    while ($row = $result->fetchAssoc()) {
      // Do something with:
      //    $row['name']
      //    $row['quantity']
    }
  }
?>

使用LIKE查询

<?php
$result = db_query('SELECT nid, title FROM {node} WHERE type = :type AND title LIKE :title', array(
    ':type'  => 'content_type',
    ':title' => "%$title%",
  ));
  if ($result) {
    while ($row = $result->fetchAssoc()) {
      // Do something with:
      //    $row['nid']
      //    $row['title']
    }
  }
?>