来源:http://trac.seagullproject.org/wiki/Howto/DB/CodeExamples/Extended

DB Queries

介绍

Seagull使用PEAR::DB作为它的抽象层。PEAR::DB给开发人员很大的灵活性使他们可以在不同的数据库厂商之间移植SQL。同时它也比直接使用PHP的SQL函数来对数据库的查询变得更加简单简洁。

概述

在Seagull中使用PEAR::DB要注意下面几点:

  • 一定要用sequences,不要使用MySQL'S的自增特性,因为这会使得移植你的SQL到其它数据库,如Postgres,更加困难。
  • Seagull重写了标准PEAR::DB从一个给定sequence中取一下个ID的方法。应用程序接口是一样的,但是为避免数据库存在大量的表我们把所有的sequences放到一个表中(在安装时选择MySQL_SGL即可)。当然,你可也可以将MySQL sequences改回到PEAR标准的处理方式,这取决于用户。
  • PEAR::DB为查询结果的格式提供了三种选择:DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC, DB_FETCHMODE_OBJECT —Seagull默认使用对象模式,但是你可以在任何时候改写。
  • Seagull允许你在一个页面同时查询多个数据库,只需给SGL_DB::singleton()实例传递一个特定的$dsn。
  • 所有的查询只使用一个数据库源(除非使用了多数据库查询)。这个数据源是通过一个单键连接资源取得的。

返回适当的数据结构

对象数组

下列查询:

  $dbh = & SGL_DB::singleton();
  $query = '
      SELECT
          b.block_id, b.name, b.title, b.title_class, 
          b.body_class, b.is_onleft
      FROM    block b, block_assignment ba
      WHERE   is_enabled = 1
      AND     b.block_id = ba.block_id
      AND     ( ba.section_id = 0 OR ba.section_id = ' . 
              $this->_currentSectionId . ' )
      ORDER BY blk_order
  ';
  $aResult = $dbh->getAll($query);

将返回下列数据结构:

 Array
(
  [0] => stdClass Object
      (
          [block_id] => 10
          [name] => SampleRightBlock1
          [title] => Sample Right Block
          [title_class] => 
          [body_class] => 
          [is_onleft] => 0
      )
  [1] => stdClass Object
      (
          [block_id] => 1
          [name] => SiteNews
          [title] => Site News
          [title_class] => 
          [body_class] => 
          [is_onleft] => 1
      )
  [...] 

单值

下列查询:

  $dbh = & SGL_DB::singleton();
  $query = "  SELECT label 
              FROM " . $conf['table']['category'] . "
              WHERE category_id = '$id'";  
  $result = $dbh->getOne($query);

将返回下列数据结构:

myLabel

单行

下列查询:

  $dbh = & SGL_DB::singleton();
  $query = "
      SELECT  usr_id, user_group_id
      FROM " . $conf['table']['user'] . "
      WHERE   username = " . $dbh->quote($username) . "
      AND     passwd = '" . md5($password) . "'
      AND     is_acct_active = 1
      AND     user_group_id <> " . SGL_UNASSIGNED;
  $aResult = $dbh->getRow($query, DB_FETCHMODE_ASSOC);

将返回下列数据结构:

Array
(
  [usr_id] => 2
  [user_group_id] => 2
)

多维数组

下列查询:

  $dbh = & SGL_DB::singleton();
  $query = "  SELECT category_id, label 
              FROM " . $conf['table']['category'] . "
              WHERE parent = $id";
  $result = $dbh->query($query);
  $count = 0;
  $aChildren = array();
  while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC)) {
      $aChildren[$count]['category_id'] = $row['category_id'];   
      $aChildren[$count]['label'] = $row['label'];
      $count++;
  }

将返回下列数据结构:

Array
(
  [0] => Array
      (
          [category_id] => 1
          [label] => Sample Category
      )
  [1] => Array
      (
          [category_id] => 4
          [label] => General
      )
  [2] => Array
      (
          [category_id] => 115
          [label] => Javascript tutorial
      )
  [3] => Array
      (
          [category_id] => 118
          [label] => Planets
      )
  [4] => Array
      (
          [category_id] => 300
          [label] => Continents
      )
)

哈希

下列查询:

  $dbh = & SGL_DB::singleton();
  $query = "
       SELECT  i.item_id,
               ia.addition
       FROM    item i, item_addition ia, item_type it, item_type_mapping itm
       WHERE   ia.item_type_mapping_id = itm.item_type_mapping_id
       AND     it.item_type_id  = itm.item_type_id
       AND     i.item_id = ia.item_id
       AND     i.item_type_id = it.item_type_id
       AND     itm.field_name = 'title'
       AND it.item_type_id  = '5'         /* Static Html Article */
       AND i.status  > " . SGL_STATUS_DELETED . "
       ORDER BY i.last_updated DESC
  ";
  $res = $dbh->getAssoc($query);

将返回下列数据结构:

Array
(
  [1] => Content Reshuffle
  [3] => Little
  [6] => Mary
  [11] => Had a Lamb
)

预备查询

预备查询可以节省你很多时间,如:

  $dbh = & SGL_DB::singleton();
  $sth = $dbh->prepare("  UPDATE " . $conf['table']['user'] . "
                          SET user_group_id = $gid
                          WHERE usr_id = ?");
  foreach ($aUsers as $uid => $username) {
      //  if attempt to remove admin (uid = 1), silently ignore
      if ($uid == 1) {
          continue;
      }
      $dbh->execute($sth, $uid);
  }

对象关系映射

关于DB_DataObject

很多PEAR开发人员喜欢使用DataObject,DataObject将SQL抽象成对象的接口。有很多相关教程。一个简单的例子是:

  $oUser = & new DataObjects_Usr();
  //  get limit and totalNumRows
  $totalNumRows = $oUser->count();
  $limit = $_SESSION['prefs']['resPerPage'];
  $oUser->orderBy($input->sortBy . ' ' . $input->sortOrder);
  $oUser->limit($input->from, $limit);
  $oUser->orderBy('date_created DESC');
  //  execute query
  $numRows = $oUser->find();
  $aUsers = array();
  if ($numRows > 0) {
      while ($oUser->fetch()) {
          $oUser->getLinks('link_%s');
          $aUsers[] = clone($oUser);
      }
      return $aUsers;
  }

检查DB错误

如果发生了错误,PEAR::DB会返回一个错误对象。你可像这样简单的进行检查:

// $aRes is the result of the query

if (!PEAR::isError($aRes)) {
    return $aRes;
} elseif (PEAR::isError($aRes, DB_ERROR_NOSUCHTABLE)) {
    SGL::raiseError('You have a Seagull database with no tables ...',
        SGL_ERROR_NODATA, PEAR_ERROR_DIE);
} else {
    SGL::raiseError('Unknown DB error occurred, pls file bug',
        SGL_ERROR_NODATA, PEAR_ERROR_DIE);
}
 
howto/db/codeexamples/extended.txt · 最后更改: 2010/05/30 00:21 (外部编辑)
 
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2