首页 > 代码库 > Moodle 中文 API 之 数据管理API

Moodle 中文 API 之 数据管理API

Data API

这篇文章描述了操作数据库的相关函数,因为他们对不同的关系型数据库做了很好的封装,所以你可以更好的使用它们而不用去考虑数据库的兼容性。

目录

   1. 主要信息 

   2. 相关函数

      2.1 获取单条记录 

      2.2 获取hash 数组记录 

      2.3 获取作为 键/值对的 关联数组

      2.4 查看多少记录匹配一个给定的条件

      2.5 查看一条记录是否存在

      2.5.1 例子

           2.5.1.1  get_records() 方法

           2.5.1.2  get_records_select() 方法

           2.5.1.3  get_records_sql() 方法

           2.5.1.4  get_records_list() 方法

           2.5.1.5  get_records_menu() 方法

           2.5.1.6  get_records_select_menu() 方法

           2.5.1.7  get_records_sql_menu() 方法

2.6 从一条记录中获取一个字段值

2.7 从多条记录中获取一个字段值

2.8 在数据库中设置一个字段值

2.9 删除多条记录

2.10 插入多条记录

     2.10.1 简单的例子

2.11 更新记录

2.12 使用记录集合

2.13 处理事务

    2.13.1 例子

2.14  SQL交互函数

2.15  调试函数

3.  特殊事件

   3.1  get_course 函数

   3.2  get_courses 函数



 

1. 主要信息 

重要提醒: 所有函数适用在 Moodle 2.0升级后, 我们改变了数据操作的一些新特性. 如果你仍在使用以前的版本,请在官网上查找相关说明。

所有方法的调用都必须使用全局对象 $DB, 因此你必须声明它:

global $DB;

· $DB 是moodle_database类的一个实例,在moodle_database.php 中定义 

· 所有的 $table 都不需要加表的前缀,如下:

$user = $DB->get_record('user', array('id'=>'1'));

· 当我们使用形如 xxx_sql() 函数时,表名如果用大括号包裹,那么必须关闭大括号。

$user = $DB->get_record_sql('SELECT * FROM {user} WHERE id = ?', array(1));

所有的$conditions 参数在函数中是以fieldname=>fieldvalue元素的形式存在的

$user = $DB->get_record('user', array('firstname'=>'Martin', 'lastname'=>'Dougiamas'));

· 所有流出来的问号参数 $params 如下。

$DB->get_record_sql('SELECT * FROM {user} WHERE firstname = ? AND lastname = ?', array('Martin', 'Dougiamas'));

///命名代替。注意命名必须唯一

$DB->get_record_sql('SELECT * FROM {user} WHERE firstname = :firstname AND lastname = :lastname',
      array('firstname'=>'Martin', 'lastname'=>'Dougiamas'));

2. 相关函数

   2.1 获取单条记录 

$DB->get_record($table, array $conditions, $fields='*', $strictness=IGNORE_MISSING)
  /// 当所有条件满足时会从数据库会从数据库获取一条记录并以对象返回这条记录
 /// int型参数 $strictness IGNORE_MISSING 意味着编译的模式,记录没找到 会返回假, 没找到会出现调试信息
 /// IGNORE_MULTIPLE 意味着返回第一条数据如果出现多条的话
 /// MUST_EXIST 意味着如果记录不存在会抛出异常

 $DB->get_record_select($table, $select, array $params=null, $fields='*', $strictness=IGNORE_MISSING)
/// 得到一条记录

$DB->get_record_sql($sql, array $params=null, 
$strictness=IGNORE_MISSING)
/// 通过 sql 语句 获取一条记录

 2.2 获取hash 数组记录

每一种方法返回的都是一个对象数组. 数组的索引来自查询结果的第一个字段. 因此为了确保数据的完整性, 查询的时候必须确保第一个字段为id. 

$DB->get_records($table, array $conditions=null, $sort='', $fields='*', $limitfrom=0, $limitnum=0)
/// 得到一组记录
 $DB->get_records_select($table, $select, array $params=null, $sort='', $fields='*', $limitfrom=0, $limitnum=0)
  /// 得到一组记录
$DB->get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0)
/// 通过sql 得到一组记录
$DB->get_records_list($table, $field, array $values, $sort='', $fields='*', $limitfrom='', $limitnum='')
/// 得到一组记录当字段 field 的值在values数组中出现时.

2.3 获取作为 键/值对的 关联数组

$DB->get_records_menu($table, array $conditions=null, $sort='', $fields='*', $limitfrom=0, $limitnum=0)
 /// 获取一组记录中的前两列作为一个关联数组
$DB->get_records_select_menu($table, $select, array $params=null, $sort='', $fields='*', $limitfrom=0, $limitnum=0)
///  获取一组记录中的前两列作为一个关联数组
$DB->get_records_sql_menu($sql, array $params=null, $limitfrom=0, $limitnum=0)
 ///  通过sql 查询获取一组记录中的前两列作为一个关联数组

2.4 查看多少记录匹配一个给定的条件

$DB->count_records($table, array $conditions=null)
/// 统计记录条数
 $DB->count_records_select($table, $select, array $params=null, $countitem="COUNT('x')")
/// 统计记录条数
 $DB->count_records_sql($sql, array $params=null)
 /// 统计记录条数 SQL SELECT COUNT(...) 查询语句.

2.5 查看一条记录是否存在

$DB->record_exists($table, array $conditions=null)
/// 检查满足条件的记录是否存在
$DB->record_exists_select($table, $select, array $params=null)
/// 检查满足条件的记录是否存在
$DB->record_exists_sql($sql, array $params=null)
/// 检查一条sql是否能返回任何记录

2.5.1 例子

2.5.1.1  get_records() 方法

得到一个对象数组

///得到所有满足 foo = bar 的记录
$result = $DB->get_records($table,array('foo'=>'bar'));

///得到所有满足foo = bar 且 jon = doe 的记录
$result = $DB->get_records($table,array('foo' => 'bar' , 'jon' => 'doe'));

///得到所有满足 foo = bar, 且只返回记录字段 foo,bar,jon,doe 
$result = $DB->get_records($table,array('foo'=>'bar'),null,'foo,bar,jon,doe').

2.5.1.2  get_records_select() 方法

注意记录中的第一项会作为数组键的id 必须保证唯一性

///得到所有 where jon = 'doe' and  bob 不= 'tom' 的记录
/// 'select'(如果不为空) 参数会直接放在where子句后面
$table = 'foo';
$select = "jon = 'doe' AND bob <> 'tom'"; //放到where子句后面
$result = $DB->get_records_select($table,$select);

2.5.1.3  get_records_sql() 方法

这种方法在每种数据库中都能使用

///得到所有记录满足'table' where foo = bar
$result = $DB->get_records_sql('SELECT * FROM {table} WHERE foo = ?', array('bar'));

//多个条件
$result = $DB->get_records_sql('SELECT * FROM {table} WHERE foo = ? AND bob = ?', array( 'bar' , 'tom' ));

2.5.1.4  get_records_list() 方法

得到一组记录中字段值为指定集合中的值得记录。

///等价于匹配 where foo in ('bar', 'elephant', 'moodle') 
$result = $DB->get_records_list($table, 'foo', array( 'bar', 'elephant', 'moodle'));

///匹配结果同上,但是只返回字段 'id', 'test' and 'taco'
$result = $DB->get_records_list($table, 'foo', array( 'bar', 'elephant', 'moodle'), null, 'id,test,taco');

2.5.1.5  get_records_menu() 方法

如果不指定字段默认返回的是记录前两个字段组成的关联数组,请注意不指定或者指定请务必保证第一个出现的字段值唯一.

$table = 'foo'; ///表名
$conditions = array('foo'=>'bar'); ///满足条件
$result = $DB->get_records_menu($table,$conditions));

///指定返回的 两个字段 'id' and 'tacos'
$table = 'foo'; 
$conditions = array('foo'=>'bar'); 
$sort = 'id'; //排序字段
$fields = 'id, tacos'; ///
$result = $DB->get_records_menu($table,$conditions,$sort,$fields));  //未指定返回字段时 记录的前两列将被返回

返回的结果可能如下:

/// id 字段的值为 909,  tacos字段的值为 6
array(1) { [909]=6 }

2.5.1.6  get_records_select_menu() 方法

函数功能 同 2.5.1.5 只是我们直接写入where子句条件了

$table = 'foo';
$select = 'jon = "doe" AND bob != "tom" '; 
$result = $DB->get_records_select_menu($table,$select);

$table = 'foo';
$select = 'jon = "doe" AND bob != "tom" '; 
$params = null;
$fields = 'id, tacos';
$sort = 'id'; 
$result = $DB->get_records_select_menu($table,$select,$params,$sort,$fields);


返回的结果可能如下:

/// id 字段的值为 909,  tacos字段的值为 6
array(1) { [909]=6 }


2.5.1.7  get_records_sql_menu() 方法

功能同上,注意一下sql语句的 不同写法

$sql = 'SELECT * FROM foo WHERE bar = ?';
$params = array(6);

$result = $DB->get_records_sql_menu($sql,$params);

//指定字段时的写法
$sql = 'SELECT id,tacos FROM foo WHERE bar = ?';
$params = array(6);

$result = $DB->get_records_sql_menu($sql,$params);

返回的结果可能如下:

/// id 字段的值为 909,  tacos字段的值为 6
array(1) { [909]=6 }


2.6 从一条记录中获取一个字段值

参数 $return 是要return 的字段名会直接返回字段的值

$DB->get_field($table, $return, array $conditions, $strictness=IGNORE_MISSING)
$DB->get_field_select($table, $return, $select, array $params=null, $strictness=IGNORE_MISSING)
//注意select 只能是一个字段哦
$DB->get_field_sql($sql, array $params=null, $strictness=IGNORE_MISSING)

2.7 从多条记录中获取一部分字段值

$DB->get_fieldset_select($table, $return, $select, array $params=null)
/// 得到单个字段返回的多个值
$DB->get_fieldset_sql($sql, array $params=null)
/// 查询第一个字段作为反悔的结果集

2.8 在数据库中设置一个字段值

$DB->set_field($table, $newfield, $newvalue, array $conditions=null)
 /// 舌质淡个字段值
$DB->set_field_select($table, $newfield, $newvalue, $select, array $params=null)
/// 设置单个满足条件的字段值

2.9 删除多条记录

$DB->delete_records($table, array $conditions=null)
/// 删除满足条件的记录
$DB->delete_records_select($table, $select, array $params=null)
/// 删除满足条件的记录

2.10 插入多条记录

这个方法插入叫做多条记录不太合适, 他是通过insert_record()函数实现插入单条记录实现的. 四个参数中的最后一个基本上不会被用到。

$DB->insert_record($table, $dataobject, $returnid=true, $bulk=false)
/// 插入一条记录 并返回插入id

2.10.1 简单的例子

$record = new stdClass();
$record->name         = 'overview';
$record->displayorder = '10000';
$DB->insert_record('quiz_report', $record, false);
$record = new stdClass();
$record->name         = 'overview';
$record->displayorder = '10000';
$lastinsertid = $DB->insert_record('quiz_report', $record);

2.11 更新记录

$DB->update_record($table, $dataobject, $bulk=false)
/// 更新一条记录
/// $dataobject 要更新的字段组成的对象
/// 注意 $dataobject 必须包含“id”字段 来查找更新
/// 参数 $table 表名
/// 参数 $dataobject 一个对象等价于fieldname=>fieldvalue.
///        必须有id字段 去匹配查找要更新的记录
/// 参数 $bulk true 意味着可以更新重复值

如果你需要写一个复杂的更新使用sql语句的话,你可以使用 ‘execute‘ 方法. 

$DB->execute($sql, array $parms=null)
 /// 仅作sql 查询,请在其他方法都无法满足的条件下使用
 /// 不要用这个方法改变数据库的结构 请用其他方法代替
 /// 参数 $sql  查询语句
 /// 参数 $params 查询参数
/// 返回真或者抛出异常

2.12 使用记录集合

经常的我们会在数据库中浏览一组记录, 而 get_records_xxx() 系列函数都不是最佳的函数, 因为它们都加载了所有的记录在内存中. 这种情况下我们高度提倡使用 get_recordset_xxx() 系列函数代替, 他有一个优秀的迭代器节省很多内存资源。

注意:别忘了关闭集合在使用完它们后。(它将会释放一系列资源在RDBMS).

这儿有一个一般的方式遍历记录在使用 get_recordset_xxx() 系列函数时:

$rs = $DB->get_recordset(....) {
foreach ($rs as $record) {
    // 你的代码
}
$rs->close(); // 这一句一定要
它的系列函数如下,用法同get_records_xxx() 系列函数 :
$DB->get_recordset($table, array $conditions=null, $sort='', $fields='*', $limitfrom=0, $limitnum=0)

$DB->get_recordset_select($table, $select, array $params=null, $sort='', $fields='*', $limitfrom=0, $limitnum=0)
.
$DB->get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0);

$DB->get_recordset_list($table, $field='', $values='', $sort='', $fields='*', $limitfrom='', $limitnum='')

不像 get_record 系列函数, 你不能使用 $rs == true 或 !empty($rs) 来判断是否有记录被找到,你可以使用下面的方法代替(迭代器标准的查看是否为空)

if ($rs->valid()) {
    // 遍历你的记录在这里.
}

2.13 处理事务

· 请注意一些数据库不支持事务 (像 MyISAM MySQL 数据库引擎), 但是所有站点管理员都强力推荐前以数据库使他们支持事务(比如 InnoDB MySQL 数据库引擎).

· 早先的版本只支持一级事务.  Moodle 2.0以后, 这个 DML 几乎支持大部分事务.

· 在Moodle 的核心中,事务不应该被大量使用; 他们更多的是在插件中被有目的使用像web services, enrol 和 同步 插件.

· 一些子系统 (像 messaging 邮件系统) 不支持事务因为他不可能回滚在外部系统中.

一个事务开始如下:

$transaction = $DB->start_delegated_transaction();

事务结束语句:

$transaction->allow_commit();

通常当抛出异常时事务会回滚. 

$transaction->rollback($ex); 必须小心使用因为他可能破坏和不支持事务数据库之间的通道.事务不能被使用在未知的代码流中; 他们只能使用在保护性极强的数据常文本中.

2.13.1 例子

global $DB;
try {
     $transaction = $DB->start_delegated_transaction();
     // 插入记录
     $DB->insert_record('foo', $object);
     $DB->insert_record('bar', $otherobject);
     // 假设这两个同时插入, 
     $transaction->allow_commit();
} catch(Exception $e) {
     $transaction->rollback($e); //抛出异常时回滚
}

2.14  SQL交互函数

为了有真正的数据库交互能力, 这里有一些交互函数用来建立 SQL 分段 基于DB Moodle 运行的时候. 使用它们我们可以避免传统的到处查询.

$DB->sql_bitand($int1, $int2)
/// 返回的 SQL 文本 表示了 两个整数间的 “且”操作
$DB->sql_bitnot($int1)
/// 返回的 SQL 文本 表示了  “非”操作
$DB->sql_bitor($int1, $int2)
/// 返回的 SQL 文本 表示了 两个整数间的 “或”操作
$DB->sql_bitxor($int1, $int2)
/// 返回的 SQL 文本 表示了 两个整数间的 “异或”操作

$DB->sql_null_from_clause()
/// Returns the FROM clause required by some DBs in all SELECT statements.

$DB->sql_ceil($fieldname)
// 返回字段的取整表达式.

$DB->sql_like($fieldname, $param, $casesensitive = true, $accentsensitive = true, $notlike = false, $escapechar = ' \\ ')
/// 返回合适的sql 实现like功能 如下例子:
  $DB->get_records_sql('SELECT ...  WHERE '.$DB->sql_like('idnumber', ':idnum').' ... ', array( 'idnum' => 'foo'));
/// 注意: 使用 $DB->sql_like_escape(...) 当用户输入来自表单的时候.

$DB->sql_length($fieldname)
/// 返回sql文本帮助统计字段长度
$DB->sql_modulo($int1, $int2)
/// Returns the SQL text to be used in order to calculate module - remainder after division
$DB->sql_position($needle, $haystack)
/// 返回查找子串的sql 语句.
/// 注意: 如果同时使用替换文本 在 $needle 和 $haystack中, 那他们必须命名替换名字.
$DB->sql_substr($expr, $start, $length=false)
/// 返回子串 的sql 文本
/// 注意: 这个函数在 Moodle 2.0 需要至少两个参数
 /// 注意: 现在他返回整个sql代替仅仅函数的部分

$DB->sql_cast_char2int($fieldname, $text=false)
  /// Returns the SQL to be used in order to CAST one CHAR column to INTEGER.
$DB->sql_cast_char2real($fieldname, $text=false)
  /// Returns the SQL to be used in order to CAST one CHAR column to REAL number.

$DB->sql_compare_text($fieldname, $numchars=32)
  /// Returns the SQL text to be used to compare one TEXT (clob) column.
  /// with one VARCHAR column.
$DB->sql_order_by_text($fieldname, $numchars=32)
  /// Returns the SQL text to be used to order by one TEXT (clob) column.

$DB->sql_concat()
  /// Returns the proper SQL to do CONCAT between the elements passed.
$DB->sql_concat_join($separator="' '", $elements=array())
  /// Returns the proper SQL to do CONCAT between the elements passed using one separator.
$DB->sql_fullname($first='firstname', $last='lastname')
  /// Returns the proper SQL to concatenate $firstname and $lastname.
$DB->sql_isempty($tablename, $fieldname, $nullablefield, $textfield)
  /// Returns the proper SQL to know if one field is empty.
$DB->sql_isnotempty($tablename, $fieldname, $nullablefield, $textfield)
  /// Returns the proper SQL to know if one field is not empty.
$DB->sql_empty()
  /// Returns the empty string char used by every supported DB.

2.15  调试函数

如果你执行

$DB->set_debug(true)

那么 $DB 将会输出每个执行的sql语句, 并伴随着时间信息. 这可能会有用在调试你的代码的时候. 显然, 调试结束后这样的代码要被移除。

 

 

3. 特殊事件

   3.1  get_course 函数

从Moodle 2.5.1 以后, 你应该使用get_course 函数代替使用 get_record(‘course‘, ...) 如果你想得到一个课程记录基于他的ID的话, 尤其是如果这个课程在当前页面上已经加载过了.那么你就可以节省一次数据库查询。

另一个优点就是这段代码更短,易读:

$course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);

替换为

$course = get_course($courseid);

3.2  get_courses 函数

如果你想得到当前所有的课程使用:

$courses = get_courses();


大概数据库的操作就是这些,有精辟见解的可以评论补充。







Moodle 中文 API 之 数据管理API