欢迎各位兄弟 发布技术文章
这里的技术是共享的
菜单项代码:
$items['breadcrumb/%breadcrumb2/edit'] = array(
'page callback' => 'breadcrumb2_page_edit',
'page arguments' => array(1),
'access arguments' => array('administer breadcrumbs'),
'weight' => 0,
'title' => 'Edit',
'type' => MENU_LOCAL_TASK,
'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
'file' => 'breadcrumb2.admin.inc',
);
这里在菜单项里面,用到了'context',它的含义可以参看第一集。接着我们向breadcrumb2.admin.inc添加breadcrumb2_page_edit函数:
/**
* Breadcrumb edit page.
*/
function breadcrumb2_page_edit($breadcrumb){
return drupal_get_form('breadcrumb2_form', $breadcrumb);
}
由于我们在前面创建面包屑的时候,编写breadcrumb2_form表单时,同时考虑了编辑时会用到,所以我们这里的代码就简洁了很多。将添加表单、编辑表单合二为一,这是一个好习惯。
来自 http://www.thinkindrupal.com/node/5760
首先我们实现删除按钮的提交处理函数breadcrumb2_form_submit_delete:
/**
* Breadcrumb form submit handler for the delete button.
*/
function breadcrumb2_form_submit_delete($form, &$form_state) {
$breadcrumb = $form_state['breadcrumb'];
$form_state['redirect'] = 'breadcrumb/' . $breadcrumb->bid . '/delete';
}
在这里,当删除一个面包屑时,我们直接将它重定向到了对应的删除页面。对应路径的菜单项是这样定义的:
$items['breadcrumb/%breadcrumb2/delete'] = array(
'page callback' => 'drupal_get_form',
'page arguments' => array('breadcrumb2_delete_confirm_form', 1),
'access arguments' => array('administer breadcrumbs'),
'weight' => 1,
'title' => 'Delete',
'type' => MENU_LOCAL_TASK,
'context' => MENU_CONTEXT_INLINE,
'file' => 'breadcrumb2.admin.inc',
);
breadcrumb2_delete_confirm_form是一个确认表单,我们把它的定义添加到breadcrumb2.admin.inc里面:
/**
* Confirm form for deleting a profile.
*/
function breadcrumb2_delete_confirm_form($form, &$form_state, $breadcrumb) {
$form_state += array('breadcrumb' => $breadcrumb);
$confirm_question = t('Are you sure you want to delete breadcrumb for path %path?', array('%path' => $breadcrumb->path));
return confirm_form($form, $confirm_question, 'breadcrumb/' . $breadcrumb->bid);
}
确认表单,采用了confirm_form,让Drupal系统来生成这个表单。最后我们来看一下,确认表单提交后的代码:
function breadcrumb2_delete_confirm_form_submit($form, &$form_state) {
$breadcrumb = $form_state['breadcrumb'];
$breadcrumb->delete();
drupal_set_message(t('Deleted breadcrumb for path %path.', array('%path' => $breadcrumb->path)));
$form_state['redirect'] = 'admin/structure/breadcrumbs';
}
这里面的代码,主要借鉴了Profile2里面的profile2_page.inc文件里面的代码。
来自 http://www.thinkindrupal.com/node/5761
我们这里是手动的创建Breadcrumb link字段,我们希望在安装这个Breadcrumb2模块的时候,自动的帮我们创建这个字段。这个字段,对我们来说是必须的。首先,我们把现有的字段的信息导出来。这里我们使用Features模块。
这是Features导出来的代码:
/**
* Implements hook_field_default_fields().
*/
function breadcrumb_link_field_default_fields() {
$fields = array();
// Exported field: 'breadcrumb2-breadcrumb2-field_breadcrumb_link'
$fields['breadcrumb2-breadcrumb2-field_breadcrumb_link'] = array(
'field_config' => array(
'active' => '1',
'cardinality' => '-1',
'deleted' => '0',
'entity_types' => array(),
'field_name' => 'field_breadcrumb_link',
'foreign keys' => array(),
'indexes' => array(),
'module' => 'link',
'settings' => array(
'attributes' => array(
'class' => '',
'rel' => '',
'target' => 'default',
),
'display' => array(
'url_cutoff' => 80,
),
'enable_tokens' => 1,
'title' => 'optional',
'title_maxlength' => 128,
'title_value' => '',
'url' => 0,
),
'translatable' => '0',
'type' => 'link_field',
),
'field_instance' => array(
'bundle' => 'breadcrumb2',
'default_value' => NULL,
'deleted' => '0',
'description' => '',
'display' => array(
'default' => array(
'label' => 'above',
'module' => 'link',
'settings' => array(),
'type' => 'link_default',
'weight' => 1,
),
),
'entity_type' => 'breadcrumb2',
'field_name' => 'field_breadcrumb_link',
'label' => 'Breadcrumb Link',
'required' => 0,
'settings' => array(
'attributes' => array(
'class' => '',
'configurable_title' => 0,
'rel' => '',
'target' => 'default',
'title' => '',
),
'display' => array(
'url_cutoff' => '80',
),
'enable_tokens' => 1,
'title' => 'required',
'title_maxlength' => '128',
'title_value' => '',
'url' => 'optional',
'user_register_form' => FALSE,
'validate_url' => 1,
),
'widget' => array(
'active' => 0,
'module' => 'link',
'settings' => array(),
'type' => 'link_field',
'weight' => '2',
),
),
);
// Translatables
// Included for use with string extractors like potx.
t('Breadcrumb Link');
return $fields;
}
我把它改造了一下,放到了install文件里面了,我们这里并没有打算依赖于Features模块:
/**
* Implements hook_install().
*/
function breadcrumb2_install() {
// Add or remove the link field, as needed.
$field = field_info_field('link');
if (empty($field)) {
$field = array(
'cardinality' => '-1',
'entity_types' => array('breadcrumb2'),
'field_name' => 'link',
'module' => 'link',
'type' => 'link_field',
);
$field = field_create_field($field);
}
$instance = field_info_instance('breadcrumb2', 'link', 'breadcrumb2');
if (empty($instance)) {
$instance = array(
'bundle' => 'breadcrumb2',
'default_value' => NULL,
'deleted' => '0',
'description' => '',
'display' => array(
'default' => array(
'label' => 'above',
'module' => 'link',
'settings' => array(),
'type' => 'link_default',
'weight' => 1,
),
),
'entity_type' => 'breadcrumb2',
'field_name' => 'link',
'label' => 'Breadcrumb Link',
'required' => 0,
'settings' => array(
'attributes' => array(
'class' => '',
'configurable_title' => 0,
'rel' => '',
'target' => 'default',
'title' => '',
),
'display' => array(
'url_cutoff' => '80',
),
'enable_tokens' => 1,
'title' => 'required',
'title_maxlength' => '128',
'title_value' => '',
'url' => 'optional',
'user_register_form' => FALSE,
'validate_url' => 1,
),
'widget' => array(
'active' => 0,
'module' => 'link',
'settings' => array(),
'type' => 'link_field',
'weight' => '2',
),
);
$instance = field_create_instance($instance);
}
}
在卸载我们的模块时,我们还需要负责将其删除:
/**
* Implements hook_uninstall().
*/
function breadcrumb2_uninstall() {
$instance = field_info_instance('breadcrumb2', 'link', 'breadcrumb2');
if (!empty($instance)) {
field_delete_instance($instance);
}
$field = field_info_field('link');
if ($field) {
field_delete_field('link');
}
}
注意这里面的field_info_field、field_create_field、field_info_instance、field_create_instance、field_delete_instance、field_delete_field等Drupal API函数的用法。它们用来获取字段信息、创建一个字段、获取字段实例信息、创建一个字段实例、删除一个字段实例、删除一个字段。
我刚开始的时候,这样写的代码:
field_delete_field($field);
结果在卸载模块的时候,总是报错,卸载不了。后来才修正过来。所以用的时候要小心。要明白这个函数里面各个参数的具体含义。
来自 http://www.thinkindrupal.com/node/5762
我们这个模块,是用来设置页面上面的面包屑的,开发了这么多,我们看看如果通过我们的面包屑实体来设置面包屑。向module文件添加以下代码:
/**
* Implements hook_page_alter().
*/
function breadcrumb2_page_alter() {
// See if current page has path breadcrumbs.
$breadcrumbs = drupal_get_breadcrumb();
$current_path = current_path();
$breadcrumb2 = breadcrumb2_load_by_path($current_path);
if(empty($breadcrumb2)){
return;
}
//$breadcrumb2 = breadcrumb2_load(1);
$wrapper = entity_metadata_wrapper('breadcrumb2', $breadcrumb2);
$breadcrumb_links = $wrapper->link->value();
foreach($breadcrumb_links as $breadcrumb_link){
$breadcrumbs[]= l($breadcrumb_link['title'], $breadcrumb_link['url']);
}
//print debug($breadcrumb_links);
// Set breadcrumbs for current page if it exists.
if ($breadcrumbs) {
drupal_set_breadcrumb($breadcrumbs);
}
}
这里面我们实现了hook_page_alter钩子,这个方式借鉴于path_breadcrumb模块,当然,我们也可以通过hook_preprocess_page来设置, crumbs模块里面有这种方式的实现。我们来看看这个钩子函数里面的代码,首先,我们根据当前路径,获取到面包屑实体$breadcrumb2;这里面我们对$breadcrumb2使用entity_metadata_wrapper做了封装,这样我们就可以方便的读取到实体里面字段link的数组了,这样做的好处是,不用考虑语言问题;之后对$breadcrumb_links数组进行循环,将里面的链接追加到当前面包屑数组$breadcrumbs里面;最后使用drupal_set_breadcrumb设置面包屑。
接下来,来看一下函数breadcrumb2_load_by_path的实现代码:
/**
* Fetch a breadcrumb object.
*
* @param $path
* Internal path.
* @return
* A fully-loaded $breadcrumb object or FALSE if it cannot be loaded.
*
* @see breadcrumb2_load_multiple()
*/
function breadcrumb2_load_by_path($path) {
$breadcrumbs = breadcrumb2_load_multiple(FALSE, array('path' => $path));
return reset($breadcrumbs);
}
我们直接将其委托给了breadcrumb2_load_multiple,把array('path' => $path)作为条件参数传递了过去。如果返回了面包屑对象数组,我们就使用reset将数组中的第一个对象返回。这里的逻辑非常简单,和breadcrumb2_load函数类似。不过越是简单的东西,有时候越难理解。我原来的想法是这样的,使用EntityFieldQuery,把我们的$path作为属性参数传递给它,这样EntityFieldQuery将会读取来一个包含bids的数组,我们把bids数组传递给breadcrumb2_load_multiple,获得一组面包屑对象,然后再使用reset获取第一个对象元素。
Entity API帮我们做了这些工作,为了更好的理解,我们反向追踪一下代码。
通过阅读里面的代码,我们最终找到了,SQL语句是在DrupalDefaultEntityController里面的buildQuery方法中动态构建的。有兴趣的可以看一下里面的代码。
到这里我们的面包屑实体类型就创建完毕了。当然,模块还没有写完。我们接着会写Views的集成、Rules的集成。只有当集成了Rules以后,我们这种构建面包屑的方式,才能
来自 http://www.thinkindrupal.com/node/5763
作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
和开发普通的模块一样,当需要存储数据的时候,我们需要定义自己的数据库表,这个时候,就需要定义Schema了。这个我们以前也讲过了,来看这里的定义。首先创建breadcrumb2.install文件,在里面输入以下内容:
<?php
/**
* @file
* Install, update and uninstall functions for the breadcrumb2 module.
*/
/**
* Implements hook_schema().
*/
function breadcrumb2_schema() {
$schema['breadcrumb'] = array(
'description' => 'Stores breadcrumb items.',
'fields' => array(
'bid' => array(
'type' => 'serial',
'not null' => TRUE,
'description' => t("'Primary Key: Unique breadcrumb item ID."),
),
),
'primary key' => array('bid'),
);
return $schema;
}
最上面的文件的描述说明,那段文字是直接从profile2.install里面复制过来的,下面的breadcrumb2_schema也是从那边复制过来的,只不过我们根据自己的需要做了修改。面包屑,这个实体比较简单,本来我想在这里定义一个属性path的,但是一想,自己需要为它创建一个表单元素,负责它的编辑、验证、存储,感觉有点麻烦,所以直接将它交给Field系统了。所以数据库表breadcrumb的结构非常简单,就一个bid主键,用来关联字段的,其它什么属性也没有定义。简单就好。
我们采用这样的策略,首先,定义好实体,然后向实体上面添加两个字段path、link,之后将这两个字段的定义使用Features导出来,然后把里面的定义代码复制到我们的模块里面,这样我们在安装的时候,就直接为我们的面包屑实体创建好字段了。一步一步来。
来自 http://www.thinkindrupal.com/node/5748
作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
接下来,我们创建breadcrumb2.module文件,首先输入以下代码:
<?php
/**
* @file
* Support for configurable breadcrumbs.
*/
接着,实现hook_entity_info()。
/**
* Implement hook_entity_info().
*/
function breadcrumb2_entity_info() {
$return = array(
'breadcrumb2' => array(
'label' => t('Breadcrumb'),
'plural label' => t('Breadcrumbs'),
'description' => t('Breadcrumb2 entity breadcrumbs.'),
'entity class' => 'Breadcrumb',
'controller class' => 'EntityAPIController',
'base table' => 'breadcrumb',
'fieldable' => TRUE,
'view modes' => array(
'full' => array(
'label' => t('Breadcrumb'),
'custom settings' => FALSE,
),
),
'entity keys' => array(
'id' => 'pid',
),
'bundles' => array(
'breadcrumb2' => array(
'label' => t('Breadcrumb'),
'admin' => array(
'path' => 'admin/structure/breadcrumbs',
'access arguments' => array('administer breadcrumbs'),
),
),
),
'bundle keys' => array(
'bundle' => 'type',
),
'uri callback' => 'entity_class_uri',
'access callback' => 'breadcrumb2_access',
'module' => 'breadcrumb2',
'metadata controller class' => 'Breadcrumb2MetadataController'
),
);
return $return;
}
首先,这个钩子的实现,我们主要参考了profile2_entity_info的实现,这里是以它为基础做的修改。其次,由于我们这里只有一个bundle,并且不允许创建其它的bundle,这个和user实体非常类似,所以中间的部分代码,我们借鉴的是user_entity_info的实现,我们来看一下user模块的实现:
function user_entity_info() {
$return = array(
'user' => array(
'label' => t('User'),
'controller class' => 'UserController',
'base table' => 'users',
'uri callback' => 'user_uri',
'label callback' => 'format_username',
'fieldable' => TRUE,
// $user->language is only the preferred user language for the user
// interface textual elements. As it is not necessarily related to the
// language assigned to fields, we do not define it as the entity language
// key.
'entity keys' => array(
'id' => 'uid',
),
'bundles' => array(
'user' => array(
'label' => t('User'),
'admin' => array(
'path' => 'admin/config/people/accounts',
'access arguments' => array('administer users'),
),
),
),
'view modes' => array(
'full' => array(
'label' => t('User account'),
'custom settings' => FALSE,
),
),
),
);
return $return;
}
我们的'entity keys'、'bundles'、'view modes',都是从user_entity_info借鉴过来的。所谓借鉴,就是将它们的代码复制过来,然后改成我们自己的。比葫芦画瓢。比如'entity keys',最初这个是从profile2中借鉴过来的,profile2_entity_info中这样定义的:
'entity keys' => array(
'id' => 'pid',
'bundle' => 'type',
'label' => 'label',
),
我们知道,pid是profile里面的主键,我们将它修改为bid,就成了最初的样子:
'entity keys' => array(
'id' => 'bid',
'bundle' => 'type',
'label' => 'label',
),
然后再借鉴一下user里面的实现,这个时候,我们会发现里面的'bundle'、'label'没有什么用,把它们删除,就成了现在的样子:
'entity keys' => array(
'id' => 'pid',
),
Drupal里面的很多钩子,尤其是这种带有info后缀的钩子,里面通常是一个大的数组,遇到这样的钩子,我们学习的路径,最好是找个类似的实现作为参考,当然我们还需要阅读这个钩子的文档,弄清楚里面的键值的具体含义,不过大部分键的含义,从字面上很容易理解出来,比如这里的'label'、'plural label'、'description'、'entity class'、'controller class'、'base table'、'fieldable'等。
来自 http://www.thinkindrupal.com/node/5749
作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
我们在hook_entity_info里面,有这样的设置“'path' => 'admin/structure/breadcrumbs'”,
这里所用的路径,我们需要在hook_menu里面定义一下,现在我们就来实现这个路径。向module文件中添加以下代码:
/**
* Implements hook_menu().
*/
function breadcrumb2_menu() {
$items['admin/structure/breadcrumbs'] = array(
'title' => 'Breadcrumbs',
'description' => 'Manage breadcrumbs.',
'page callback' => 'breadcrumb2_overview_breadcrumbs',
'access arguments' => array('administer breadcrumbs'),
'file' => 'breadcrumb2.admin.inc',
);
$items['admin/structure/breadcrumbs/list'] = array(
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
}
注意,我们必须把admin/structure/breadcrumbs/list指定为MENU_DEFAULT_LOCAL_TASK,这样Field模块可以在admin/structure/breadcrumbs路径后面添加两个子标签,管理字段、管理显示。
接着创建breadcrumb2.admin.inc文件,向里面添加我们的回调函数breadcrumb2_overview_breadcrumbs:
<?php
/**
* @file
* Breadcrumb administration and module settings UI.
*
*/
/**
* Displays the breadcrumb admin overview page.
*/
function breadcrumb2_overview_breadcrumbs(){
$build['#markup'] = t('Breadcrumb2 overview breadcrumbs');
return $build;
}
这里面还没有逻辑代码。我们只是想快速的实现一个骨架,然后再逐步的完善里面具体的细节。
来自 http://www.thinkindrupal.com/node/5750
作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
在我们的菜单项里面,用到了权限'administer breadcrumbs',现在就让我们定义这个权限,向module文件中添加以下代码:
/**
* Implements hook_permission().
*/
function breadcrumb2_permission() {
$permissions = array(
'administer breadcrumbs' => array(
'title' => t('Administer breadcrumbs'),
'description' => t('Edit and view all entity breadcrumbs.'),
),
);
return $permissions;
}
面包屑也有增删查改,但是这些工作都是由管理员来做的,所以我们这里比较省事,就定义了一个'administer breadcrumbs'权限,其它的都省去了。
在hook_entity_info里面,有这样的定义'access callback' => 'breadcrumb2_access',这里的breadcrumb2_access,就是一个访问控制回调函数,来看一下我们的实现:
/**
* Determines whether the given user has access to a breadcrumb.
*
* @param $op
* The operation being performed. One of 'view', 'update', 'create', 'delete'
* or just 'edit' (being the same as 'create' or 'update').
* @param $breadcrumb
* Optionally a breadcrumb to check access for. If nothing is
* given, access for all breadcrumbs is determined.
* @param $account
* The user to check for. Leave it to NULL to check for the global user.
* @return boolean
* Whether access is allowed or not.
*/
function breadcrumb2_access($op, $breadcrumb = NULL, $account = NULL) {
if (user_access('administer breadcrumbs', $account)) {
return TRUE;
}
return FALSE;
}
对于比较复杂的实体,比如profile2,这个访问回调里面还会定义一个新的钩子hook_profile2_access。
function profile2_access($op, $profile = NULL, $account = NULL) {
if (user_access('administer profiles', $account)) {
return TRUE;
}
if ($op == 'create' || $op == 'update') {
$op = 'edit';
}
// Allow modules to grant / deny access.
$access = module_invoke_all('profile2_access', $op, $profile, $account);
// Only grant access if at least one module granted access and no one denied
// access.
if (in_array(FALSE, $access, TRUE)) {
return FALSE;
}
elseif (in_array(TRUE, $access, TRUE)) {
return TRUE;
}
return FALSE;
}
在node_access里面,也定义了类似的钩子:
$access = module_invoke_all('node_access', $node, $op, $account);
当然,我们这里不需要定义一个hook_breadcrumb2_access,所以我们的就比较简单。
来自 http://www.thinkindrupal.com/node/5751
作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
对于定义的实体类型,我们最好为其实现增删改查等API函数,方便别处调用:
{entity_type}_load(),
{entity_type}_create(),
{entity_type}_save(),
{entity_type}_delete_multiple(),
Entity API模块,为我们提供了entity_create()、 entity_save()、 entity_delete()等函数,直接使用Entity API里面的即可,我们还有必要定义自己的么?最好还是定义一下,也就是有这个必要。我们来看看我们的实现:
/**
* Fetch a breadcrumb object.
*
* @param $bid
* Integer specifying the breadcrumb id.
* @param $reset
* A boolean indicating that the internal cache should be reset.
* @return
* A fully-loaded $breadcrumb object or FALSE if it cannot be loaded.
*
* @see breadcrumb2_load_multiple()
*/
function breadcrumb2_load($bid, $reset = FALSE) {
$breadcrumbs = breadcrumb2_load_multiple(array($bid), array(), $reset);
return reset($breadcrumbs);
}
/**
* Load multiple breadcrumbs based on certain conditions.
*
* @param $bids
* An array of breadcrumb IDs.
* @param $conditions
* An array of conditions to match against the {breadcrumb} table.
* @param $reset
* A boolean indicating that the internal cache should be reset.
* @return
* An array of breadcrumb objects, indexed by bid.
*
* @see entity_load()
* @see breadcrumb2_load()
*/
function breadcrumb2_load_multiple($bids = array(), $conditions = array(), $reset = FALSE) {
return entity_load('breadcrumb2', $bids, $conditions, $reset);
}
/**
* Deletes a breadcrumb.
*/
function breadcrumb2_delete(Breadcrumb $breadcrumb) {
$breadcrumb->delete();
}
/**
* Delete multiple breadcrumbs.
*
* @param $bids
* An array of breadcrumb IDs.
*/
function breadcrumb2_delete_multiple(array $bids) {
entity_get_controller('breadcrumb2')->delete($bids);
}
/**
* Create a breadcrumb object.
*/
function breadcrumb2_create($values = array()) {
return new Breadcrumb($values);
}
/**
* Saves a breadcrumb to the database.
*
* @param $breadcrumb
* The breadcrumb object.
*/
function breadcrumb2_save(Breadcrumb $breadcrumb) {
return $breadcrumb->save();
}
这都是模式化的代码,对应的实现,可以参考profile2,也可以参考model模块。
来自 http://www.thinkindrupal.com/node/5752
作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
我们在breadcrumb2_entity_info里面,将'entity class'指定为了Breadcrumb,现在我们来看看这个类的定义。向breadcrumb2.module里面添加以下代码:
/**
* The class used for breadcrumb entities
*/
class Breadcrumb extends Entity {
public function __construct($values = array()) {
parent::__construct($values, 'breadcrumb');
}
protected function defaultLabel() {
return $this->path;
}
protected function defaultUri() {
return array('path' => 'breadcrumb/' . $this->bid);
}
}
类似的代码可以参看model里面的Model类的实现。
我们将'controller class'设置为了EntityAPIController,当然,我们也可以有自己的实现,比如将其设置为BreadcrumbController。此时需要定义这个控制器类,我们向module文件追加以下代码:
/**
* The Controller for Breadcrumb entities
*/
class BreadcrumbController extends EntityAPIController {
public function __construct($entityType) {
parent::__construct($entityType);
}
/**
* Create a breadcrumb - we first set up the values that are specific
* to our breadcrumb schema but then also go through the EntityAPIController
* function.
*
* @param $type
* The machine-readable type of the breadcrumb.
*
* @return
* A breadcrumb object with all default fields initialized.
*/
public function create(array $values = array()) {
// Add values that are specific to our Breadcrumb
$values += array(
'bid' => '',
);
$breadcrumb = parent::create($values);
return $breadcrumb;
}
}
这里也是模仿的model模块的实现。
来自 http://www.thinkindrupal.com/node/5753
作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
我们将'metadata controller class'设置为了Breadcrumb2MetadataController,对于这个类型,我们将它放到了breadcrumb2.info.inc文件中了。来看一下它的代码:
<?php
/**
* @file
* Provides Entity metadata integration.
*/
/**
* Extend the defaults.
*/
class Breadcrumb2MetadataController extends EntityDefaultMetadataController {
public function entityPropertyInfo() {
$info = parent::entityPropertyInfo();
$properties = &$info[$this->type]['properties'];
return $info;
}
}
我们这里面,这个类是空类,里面其实没有自己的实现。我们是模仿profile2的,它的这个元数据控制器类,是这样定义的:
class Profile2MetadataController extends EntityDefaultMetadataController {
public function entityPropertyInfo() {
$info = parent::entityPropertyInfo();
$properties = &$info[$this->type]['properties'];
$properties['label'] = array(
'label' => t('Label'),
'description' => t('The profile label.'),
'setter callback' => 'entity_property_verbatim_set',
'setter permission' => 'administer profiles',
'schema field' => 'label',
);
…
return $info;
}
}
/**
* Implements hook_entity_property_info_alter().
*/
function profile2_entity_property_info_alter(&$info) {
…
}
我们的面包屑里面,除了bid,不包含其它属性,同时只有一个bundle,我们这里可能就不需要定义这个元数据控制器类,只需要使用Entity API提供的默认的EntityDefaultMetadataController即可。
另外需要注意的是,在这个info.inc文件里面可以定义实现钩子hook_entity_property_info_alter。如果这个钩子实现可以放在这里的话,那么也可以在这里实现hook_entity_property_info,这是我的猜测。这样做的目的也是为了减小module文件的大小。
来自 http://www.thinkindrupal.com/node/5754
作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
一切工作准备就绪,让我们启用Breadcrumb2模块,我们需要预先安装好它所依赖的模块。都准备好了。启用好模块以后,没有报错,接着我们访问admin/structure,在这里我们并没有找到我们的面包屑:
而管理字段、管理显示两个标签却显示了出来,点击这两个标签,发现它们的路径分别为admin/structure/breadcrumbs/fields,admin/structure/breadcrumbs/display。功能和我们在其它地方看到的一样。admin/structure/breadcrumbs哪里去了?
我们回过头来检查代码,发现我们在breadcrumb2_menu少写下面一句代码:
return $items;
一个很低级的错误。我们把它补上。我最初开发的时候,除了这个问题,还遇到了找不到Breadcrumb2MetadataController类的问题。因为我没有创建breadcrumb2.info.inc文件,也没有添加Breadcrumb2MetadataController的实现。我是在发现admin/structure/breadcrumbs不存在这个问题以后,清空缓存后,整个网站无法访问了,并且提示Breadcrumb2MetadataController不存在。这个时候,我才添加的breadcrumb2.info.inc文件。
现在清除缓存,admin/structure/breadcrumbs显示出来了: