2.2 慢API替换
前提条件:舍弃相关钩子机制。
提示:下面的代码,大家都可以选择性封装到自定义API使用。
一、user_save
1.为用户添加角色
db_insert('users_roles')
->fields(array('uid', 'rid'));
->values(array(
'uid' => $user->uid,
'rid' => TEMP_EDITOR_RID,
));
->execute();
2.为用户删除角色
db_delete('users_roles')
->condition('uid', $user->uid, 'rid' => TEMP_EDITOR_RID)
->execute();
3.修改密码
$data = array(
'uid' => '12',
'pass' => '123456',
);
require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
$data['pass'] = user_hash_password(trim($data['pass']));
drupal_write_record('users', $data, array('uid'));
4.保存新用户
/**
* 保存用户基本信息
*
* @param $data
* users表字段信息
*
* @return
* FALSE 失败,1 新增成功,2 更新成功
*/
function user_basic_save(&$data) {
if (isset($data['uid'])) { // 更新
if (isset($data['pass'])) { // 修改密码
require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
$data['pass'] = user_hash_password(trim($data['pass']));
}
return drupal_write_record('users', $data, array('uid'));
}
else { // 新增
require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
// 处理密码
if (isset($data['pass'])) {
$data['pass'] = user_hash_password(trim($data['pass']));
}
else {
$data['pass'] = ''; // 生成随机密码
$data['pass'] = user_hash_password(trim($data['pass']));
}
$data['uid'] = db_next_id(db_query('SELECT MAX(uid) FROM {users}')->fetchField());
$data['created'] = REQUEST_TIME;
$data['access'] = REQUEST_TIME;
$data['login'] = REQUEST_TIME;
if (!isset($data['mail'])) {
$data['mail'] = $data['name'] . '@yoursite.com';
$data['init'] = $data['name'] . '@yoursite.com';
}
$data['status'] = 1;
return drupal_write_record('users', $data);
}
}
5.修改用户基本信息
就修改users表即可,如用户名、邮箱
API同上。
6.修改用户资料信息
如:姓名、性别等,建议都放在自定义表里:{user_profile}
/**
* 保存用户信息
*
* @param $user_profile
* array('uid', 'realname', 'gender', ...)
*
* @return
* FALSE 失败,1 新增成功,2 更新成功
*/
function user_profile_save($user_profile) {
if (user_profile_load($user_profile['uid'])) { // 更新
return drupal_write_record('user_profile', $user_profile, array('uid'));
}
else { // 新增
return drupal_write_record('user_profile', $user_profile);
}
}
7.第三方用户注册时设置authmap,drupal提供的函数是:user_set_authmaps,但是它需要$user对象作为参数,我这里有时不需要user对象,所以自定义了一个函数只传uid。改动很少,大家可以自行对比下。
/**
* Save mappings of which external authentication module(s) authenticated
* a user. Maps external usernames to user ids in the users table.
*
* @param $uid
* @param $authmaps
* An associative array with a compound key and the username as the value.
* The key is made up of 'authname_' plus the name of the external authentication
* module.
* @see user_external_login_register()
*/
function custom_user_set_authmaps($uid, $authmaps) {
foreach ($authmaps as $key => $value) {
$module = explode('_', $key, 2);
if ($value) {
db_merge('authmap')
->key(array(
'uid' => $uid,
'module' => $module[1],
))
->fields(array('authname' => $value))
->execute();
}
else {
db_delete('authmap')
->condition('uid', $uid)
->condition('module', $module[1])
->execute();
}
}
}
二、node_load
1.根据nid获取节点基本信息,比如节点标题,那么直接读取node表即可。
比如,我常用的是通过id获取name,我就定义了如下API:
/**
* 获取以英文逗号分隔的多个id字符串所对应的名字
*/
function get_names_from_ids($ids, $type='term') {
$names = array();
$ids = explode(',', $ids);
switch ($type) {
case 'term':
foreach ($ids as $value) {
$names[] = ; // 从taxonomy_term_data表里获取name
}
break;
case 'node':
foreach ($ids as $value) {
$record = ; // 从node表获取title
$names[] = $record['title'];
}
break;
case 'users':
foreach ($ids as $value) {
$record = ''; // 从users表获取name
$names[] = $record['name'];
}
break;
default:
# code...
break;
}
return implode($names, ',');
}
2.读取三个及三个以上字段信息,在无性能问题的前提下,可以用node_load + entity_metadata_wrapper,主要是为了方便快捷。
$node = node_load($nid);
$node_wrapper = entity_metadata_wrapper('node', $node);
$field_1_value = $node_wrapper->field_field_1->value();
$field_2_value = $node_wrapper->field_field_2->value();
3.读取三个以下字段信息,可以分开单独查询字段表(如果典型且常用,可封装API,如:获取任务所属项目。像:获取项目图片信息,即使有多处查询,也不要封装了,无意义)
/**
* 获取项目所属机构id
*/
function get_project_institution($project_id) {
$query = db_select('field_data_field_project_company', 'fpc');
$query->condition('fpc.entity_id', $project_id);
$query->fields('fpc', array('field_project_company_target_id'));
return $query->execute()->fetchField();
}
4.内容类型可以通过相关钩子来同步一个自定义表,读取信息时就读自定义表。
如:定义一个机构信息表,{institutions},把机构内容类型的所有字段信息也都加入到这个表里,在hook_node_insert, hook_node_update, hook_node_delete时,同步更新它。这样在读取机构信息的地方,尤其是app接口里,直接读自定义的institutions表,就快多了!
三、node_save
1.假如是只修改节点标题,节点状态等node表里有的信息,可以直接操作node表。
2.假如只是修改节点的一个或两个字段信息,可以直接去操作字段表,字段version表如果没有用到的话也不用管。
四、user_load
1.获取用户基本信息,读取users表即可
/**
* 获取用户基本信息
*
* @return
* FALSE || 用户信息数组
*/
function user_basic_load($uid) {
$params = array(
'table' => 'users',
'conditions' => array('uid' => $uid),
'single' => TRUE,
);
return get_table_record_value2($params);
}
还可以扩展出:user_basic_load_by_name, user_basic_load_by_mail等自定义API。
2.获取用户角色信息,读取users_roles表即可。官方API是user_has_role,或者大家一般读取user对象里的roles信息,都需要有user对象,代价不小,因为我们有时候判断的不是当前登录用户的角色,所以不需要一直传$user。 下面举个例子,我是把每个角色的判断封装了单独的API,如判断用户是否开发者角色:
/**
* 判断用户是否是开发者角色
*/
function user_is_developer($uid = NULL) {
if (!$uid) {
global $user;
$uid = $user->uid;
}
elseif (!is_numeric($uid)) {
$uid = $uid->uid;
}
$developer_role = variable_get('user_admin_role', '');
// 查询users_roles表
// 查到了 return TRUE
return FALSE;
}
3.获取用户扩展资料信息,首先不用用户字段,直接使用自定义表,如:user_profile
/**
* 获取用户信息
*
* @return
* FALSE || 用户信息数组
*/
function user_profile_load($uid) {
// 查询user_profile表
}
还可以扩展出user_profile_load_by_phone等API。
4.第三方登录时,需要从authmap里调出用户信息,drupal提供的函数是:user_external_load,它成功时返回了user对象,有时候不需要,所以自定义一个函数,只返回uid。
/**
* Fetches a user object based on an external authentication source.
*
* @param string $authname
* The external authentication username.
*
* @return
* UID if the user is found or FALSE if not found.
*/
function custom_user_external_load($authname) {
return db_query("SELECT uid FROM {authmap} WHERE authname = :authname", array(':authname' => $authname))->fetchField();
}
五、file_load
1.其实基本上只需要读取file_managed表就能拿到常用的文件信息。
/**
* 获取文件信息
*/
function get_file_info($fid) {
$params = array(
'table' => 'file_managed',
'single' => TRUE,
'conditions' => array('fid' => $fid),
);
return get_table_record_value2($params);
}
六、file_save
1.其实基本上只需要保存到file_managed表就可以了。
/**
* 更新文件基本信息
*/
function file_basic_save(&$file) {
if (isset($file['fid'])) {
return drupal_write_record('file_managed', $file, 'fid');
}
else {
return drupal_write_record('file_managed', $file);
}
}
七、file_copy
1.如果不想生成新的文件记录,用file_unmanaged_copy代替
八、file_save_data
1.可以自定义个custom_file_save_data,区别就是不用传file对象。
/**
* 保存文件
*
* @param $data
* 文件数据
*
* @param $destination
* 文件保存路径
*
* @param $author
* 文件作者uid
*
* @param $replace
* Replace behavior when the destination file already exists:
* - FILE_EXISTS_REPLACE - Replace the existing file.
* - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
* unique.
* - FILE_EXISTS_ERROR - Do nothing and return FALSE.
*
* @return
* 文件信息数组 || FALSE
*/
function custom_file_save_data($data, $destination, $author = NULL, $replace = FILE_EXISTS_RENAME) {
if ($author === NULL) {
global $user;
$author = $user->uid;
}
// 验证路径是否合法
if (!file_valid_uri($destination)) {
return FALSE;
}
// 保存物理文件
if ($uri = file_unmanaged_save_data($data, $destination, $replace)) {
$file = array(
'uid' => $author,
'uri' => $uri,
'filename' => drupal_basename($uri),
'filemime' => file_get_mimetype($uri),
'filesize' => filesize($uri),
'status' => 1,
'timestamp' => REQUEST_TIME,
);
if (file_basic_save($file)) {
return $file;
}
else {
return FALSE;
}
}
return FALSE;
}
九、taxonomy_vocabulary_load
1.读取词汇表信息,只需要去读取taxonomy_vocabulary表即可
十、taxonomy_vocabulary_machine_name_load
1.读取词汇表信息,只需要去读取taxonomy_vocabulary表即可
/**
* 根据词汇表的机读名获取词汇表id
*/
function get_voc_id_from_machine_name($machine_name) {
// 查询taxonomy_vocabulary表
}
十一、taxonomy_term_load
1.读取术语信息,只需要去读取taxonomy_term_data表即可
常用的方法:
/**
* 根据tid获取分类名字
*/
function get_term_name_from_tid($tid) {
// 查询taxonomy_term_data表
}
/**
* 根据分类名字获取tid
*/
function get_tid_from_term_name($term_name, $vid) {
// 查询taxonomy_term_data表
}
十二、taxonomy_term_save
1.保存术语,只需要保存taxonomy_term_data和taxonomy_term_hierarchy两个表即可。
/**
* 保存术语
*/
function custom_term_save($name, $vid) {
$term = array(
'name' => $name,
'vid' => $vid,
);
if (drupal_write_record('taxonomy_term_data', $term)) {
// 保存术语等级记录
$temp = array(
'tid' => $term['tid'],
);
drupal_write_record('taxonomy_term_hierarchy', $temp);
return $term['tid'];
}
return FALSE;
}
十三、taxonomy_get_tree
1.读取词汇表下的术语信息列表,从taxonomy_term_data表自己读取组织即可
/**
* 获取词汇表一级术语数组
*
* @param $voc_machine_name
* 词汇表机读名
*
* @param $not_multiple
* 若词汇表术语为多层及,则传值TRUE,否则默认为FALSE,即:单层级
*
* @return
* 术语数组,array('tid' => 'name')
*/
function get_vocabulary_first_level_terms($voc_machine_name, $multiple = FALSE) {
$vid = get_vid_from_machine_name($voc_machine_name);
if (!$multiple) {
$query = "SELECT tid, name FROM {taxonomy_term_data} WHERE vid = :vid ORDER BY weight DESC";
}
else {
$query = "SELECT td.tid, td.name FROM {taxonomy_term_data} td INNER JOIN {taxonomy_term_hierarchy} th ON td.tid = th.tid WHERE td.vid = :vid AND th.parent = 0 ORDER BY weight DESC";
}
$result = db_query($query, array(':vid' => $vid));
$return_array = array();
foreach ($result as $value) {
$return_array[$value->tid] = $value->name;
}
return $return_array;
}