作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
曾经有人在这里,问过我一个这样的问题,我怎么没有看到SQL语句啊?我们前面讲了,在向node_page_view传递参数之前,调用了node_load函数,将节点ID转为了节点对象。我们来看一下node_load函数的定义。
/**
* Loads a node object from the database.
*
* @param $nid
* The node ID.
* @param $vid
* The revision ID.
* @param $reset
* Whether to reset the node_load_multiple cache.
*
* @return
* A fully-populated node object, or FALSE if the node is not found.
*/
function node_load($nid = NULL, $vid = NULL, $reset = FALSE) {
$nids = (isset($nid) ? array($nid) : array());
$conditions = (isset($vid) ? array('vid' => $vid) : array());
$node = node_load_multiple($nids, $conditions, $reset);
return $node ? reset($node) : FALSE;
}
它将单个节点的加载委托给了node_load_multiple,只不过这里传递过来一个节点ID而已。我们往下看node_load_multiple。
/**
* Loads node entities from the database.
*
* This function should be used whenever you need to load more than one node
* from the database. Nodes are loaded into memory and will not require database
* access if loaded again during the same page request.
*
* @see entity_load()
* @see EntityFieldQuery
*
* @param $nids
* An array of node IDs.
* @param $conditions
* (deprecated) An associative array of conditions on the {node}
* table, where the keys are the database fields and the values are the
* values those fields must have. Instead, it is preferable to use
* EntityFieldQuery to retrieve a list of entity IDs loadable by
* this function.
* @param $reset
* Whether to reset the internal node_load cache.
*
* @return
* An array of node objects indexed by nid.
*
* @todo Remove $conditions in Drupal 8.
*/
function node_load_multiple($nids = array(), $conditions = array(), $reset = FALSE) {
return entity_load('node', $nids, $conditions, $reset);
}
node_load_multiple又将具体的实现,委托给了entity_load。我们通过Google搜索一下entity_load,发现这个函数位于includes/common.inc里面,这让人有点意外。Fago对这一点就提出了批评,说entity的函数放的哪都是,Drupal8在这方面做了改进,Fago的有关实体的想法进入了内核。
不过这里面仍然没有SQL语句。我们在这个api.drupal.org上,在代码的上面,有这么一部分:
我们点击DrupalDefaultEntityController,进入页面https://api.drupal.org/api/drupal/includes%21entity.inc/class/DrupalDefaultEntityController/7,找到:
点击这里的DrupalDefaultEntityController::load。阅读这个成员函数,在代码里面找到:
我们看到SQL语句的构建,是由DrupalDefaultEntityController::buildQuery完成的,我们点击这个成员函数,查看对应的源代码,这里面,我们看到了SQL语句:
protected function buildQuery($ids, $conditions = array(), $revision_id = FALSE) {
$query = db_select($this->entityInfo['base table'], 'base');
$query->addTag($this->entityType . '_load_multiple');
if ($revision_id) {
$query->join($this->revisionTable, 'revision', "revision.{$this->idKey} = base.{$this->idKey} AND revision.{$this->revisionKey} = :revisionId", array(':revisionId' => $revision_id));
}
elseif ($this->revisionKey) {
$query->join($this->revisionTable, 'revision', "revision.{$this->revisionKey} = base.{$this->revisionKey}");
}
// Add fields from the {entity} table.
$entity_fields = $this->entityInfo['schema_fields_sql']['base table'];
if ($this->revisionKey) {
// Add all fields from the {entity_revision} table.
$entity_revision_fields = drupal_map_assoc($this->entityInfo['schema_fields_sql']['revision table']);
// The id field is provided by entity, so remove it.
unset($entity_revision_fields[$this->idKey]);
// Remove all fields from the base table that are also fields by the same
// name in the revision table.
$entity_field_keys = array_flip($entity_fields);
foreach ($entity_revision_fields as $key => $name) {
if (isset($entity_field_keys[$name])) {
unset($entity_fields[$entity_field_keys[$name]]);
}
}
$query->fields('revision', $entity_revision_fields);
}
$query->fields('base', $entity_fields);
if ($ids) {
$query->condition("base.{$this->idKey}", $ids, 'IN');
}
if ($conditions) {
foreach ($conditions as $field => $value) {
$query->condition('base.' . $field, $value);
}
}
return $query;
}
这段代码仍然很抽象,从这里面,我们可以看出,Drupal在PHP的基础之上,为我们封装了很多层。