作者:老葛,北京亚艾元软件有限责任公司,http://www.yaiyuan.com
我们在前面的Views的配置里面,已经看到,现有的功能已经基本能够满足我们的需求了。有时候,我们还需要为Views提供更多地字段,这里的更多,指的是超出了Entity API默认提供的那一部分。比如面包屑的编辑、删除链接,我们想直接提供出来,而不是通过字段覆写的方式实现。
向breadcrumb2.module文件追加以下代码:
/**
* Implements hook_views_api().
*/
function breadcrumb2_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'breadcrumb2') . '/views',
);
}
我们这里实现了钩子hook_views_api,并将我们Views集成的文件,统一放在了breadcrumb2\views目录下面,我们现在就创建这样的一个子目录文件夹。接下来,我们在这个子文件夹下面创建一个文件breadcrumb2.views.inc,并向里面添加以下代码:
<?php
/**
* @file
* Providing extra integration with views.
*/
/**
* Implements hook_views_data_alter ()
*/
function breadcrumb2_views_data_alter(&$data) {
$data['breadcrumb']['link_breadcrumb'] = array(
'field' => array(
'title' => t('Link'),
'help' => t('Provide a link to the breadcrumb.'),
'handler' => 'breadcrumb2_handler_link_field',
),
);
$data['breadcrumb']['edit_breadcrumb'] = array(
'field' => array(
'title' => t('Edit Link'),
'help' => t('Provide a link to the edit form for the breadcrumb.'),
'handler' => 'breadcrumb2_handler_edit_link_field',
),
);
$data['breadcrumb']['delete_breadcrumb'] = array(
'field' => array(
'title' => t('Delete Link'),
'help' => t('Provide a link to delete the breadcrumb.'),
'handler' => 'breadcrumb2_handler_delete_link_field',
),
);
// This content of this field are decided based on the menu structure that
// follows breadcrumb/%breadcrumb2/op
$data['breadcrumb']['operations'] = array(
'field' => array(
'title' => t('Operations links'),
'help' => t('Display all operations available for this breadcrumb.'),
'handler' => 'breadcrumb2_handler_breadcrumb_operations_field',
),
);
}
我们通过实现hook_views_data_alter (),向breadcrumb 的Views中,添加了4个字段,分别为link_breadcrumb、edit_breadcrumb、delete_breadcrumb、operations。用来方便的编辑、删除、查看、管理面包屑。
这里的$data就是一个大的数组,$data['breadcrumb']是基表,$data['breadcrumb']['edit_breadcrumb']是下面的字段,里面的title、help键就不用介绍了,handler用来指定哪个类负责处理这个字段。
对于breadcrumb2_handler_link_field ,我们需要在breadcrumb2\views下面创建一个名为breadcrumb2_handler_link_field.inc的文件,文件创建好以后,里面添加以下代码:
<?php
/**
* @file
* Contains a Views field handler to take care of displaying links to entities
* as fields.
*/
class breadcrumb2_handler_link_field extends views_handler_field {
function construct() {
parent::construct();
$this->additional_fields['bid'] = 'bid';
}
function option_definition() {
$options = parent::option_definition();
$options['text'] = array('default' => '', 'translatable' => TRUE);
return $options;
}
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$form['text'] = array(
'#type' => 'textfield',
'#title' => t('Text to display'),
'#default_value' => $this->options['text'],
);
}
function query() {
$this->ensure_my_table();
$this->add_additional_fields();
}
function render($values) {
$text = !empty($this->options['text']) ? $this->options['text'] : t('view');
$bid = $values->{$this->aliases['bid']};
return l($text, 'breadcrumb/' . $bid);
}
}
在这个文件里面,我们定义了一个类breadcrumb2_handler_link_field,它继承了类views_handler_field。在定义里面,它实现了构造函数construct,选项定义option_definition,选项表单options_form,查询query(),呈现render($values),四个成员函数。options_form就是在Views里面添加字段时,弹出来的配置表单对话框;render($values)是负责呈现这个字段的;query()里面,可以加点查询什么的,我们这里比较简单。
接下来在breadcrumb2\views下面创建一个名为breadcrumb2_handler_edit_link_field.inc的文件,文件创建好以后,里面添加以下代码:
<?php
/**
* @file
* Contains a Views field handler to take care of displaying edit links
* as fields
*/
class breadcrumb2_handler_edit_link_field extends breadcrumb2_handler_link_field {
function construct() {
parent::construct();
}
function render($values) {
// Check access.
if (!user_access('administer breadcrumbs')) {
return;
}
$text = !empty($this->options['text']) ? $this->options['text'] : t('edit');
$bid = $values->{$this->aliases['bid']};
return l($text, 'breadcrumb/' . $bid . '/edit');
}
}
breadcrumb2_handler_edit_link_field的定义就比较简单,这里归功于面向对象的继承,在呈现函数里面我们构建了一个编辑链接。
然后再创建breadcrumb2_handler_delete_link_field.inc文件,里面的代码如下:
<?php
/**
* @file
* Contains a Views field handler to take care of displaying deletes links
* as fields
*/
class breadcrumb2_handler_delete_link_field extends breadcrumb2_handler_link_field {
function construct() {
parent::construct();
}
function render($values) {
// Check access.
if (!user_access('administer breadcrumbs')) {
return;
}
$text = !empty($this->options['text']) ? $this->options['text'] : t('delete');
$bid = $values->{$this->aliases['bid']};
return l($text, 'breadcrumb/' . $bid . '/delete');
}
}
最后创建breadcrumb2_handler_breadcrumb_operations_field.inc文件,并添加以下代码:
<?php
/**
* This field handler aggregates operations that can be done on a breadcrumb
* under a single field providing a more flexible way to present them in a view
*/
class breadcrumb2_handler_breadcrumb_operations_field extends views_handler_field {
function construct() {
parent::construct();
$this->additional_fields['bid'] = 'bid';
}
function query() {
$this->ensure_my_table();
$this->add_additional_fields();
}
function render($values) {
$links = menu_contextual_links('breadcrumb2', 'breadcrumb', array($this->get_value($values, 'bid')));
if (!empty($links)) {
return theme('links', array('links' => $links, 'attributes' => array('class' => array('links', 'inline', 'operations'))));
}
}
}
在breadcrumb2_handler_breadcrumb_operations_field里面,我们使用了menu_contextual_links来返回对应的链接数组,并使用theme('links'来呈现这些链接。
如果对这里的代码,不理解的话,可以参看model里面的定义,和那里的定义是一样的。我只是修改了一下。有关Views集成的更多代码,可以直接参看Views对Drupal核心模块的支持,位于目录views\modules目录下面。在Think in Drupal的第三集里面,我曾经向Ubercart提交了一个补丁,这个补丁就是有关Views集成的。我补丁里面的代码如下,粗体部分就是我添加的:
/**
* Implements hook_views_data().
*/
function uc_order_views_data() {
...
// Ordered products.
$data['uc_order_products']['table']['group'] = t('Ordered product');
$data['uc_order_products']['table']['base'] = array(
'field' => 'order_product_id',
'title' => t('Ordered products'),
'help' => t('Products that have been ordered in your Ubercart store.'),
);
// Expose nodes to ordered products as a relationship.
$data['uc_order_products']['nid'] = array(
'title' => t('Nid'),
'help' => t('The nid of the ordered product. If you need more fields than the nid: Node relationship'),
'relationship' => array(
'title' => t('Node'),
'help' => t('Relate product to node.'),
'handler' => 'views_handler_relationship',
'base' => 'node',
'field' => 'nid',
'label' => t('node'),
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_node_nid',
),
'field' => array(
'handler' => 'views_handler_field_node',
),
);
// Expose orders to ordered products as a relationship.
$data['uc_order_products']['order_id'] = array(
'title' => t('Order ID'),
'help' => t('The order ID of the ordered product. If you need more fields than the order ID: Order relationship'),
'relationship' => array(
'title' => t('Order'),
'help' => t('Relate product to order.'),
'handler' => 'views_handler_relationship',
'base' => 'uc_orders',
'field' => 'order_id',
'label' => t('order'),
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
'field' => array(
'handler' => 'uc_order_handler_field_order_id',
),
);
// Pull in node fields directly.
$data['node']['table']['join']['uc_order_products'] = array(
'left_field' => 'nid',
'field' => 'nid',
);
// Pull in product fields directly.
$data['uc_products']['table']['join']['uc_order_products'] = array(
'left_field' => 'nid',
'field' => 'nid',
);
....
return $data;
}
我们看到,将我们的数据库表,集成到Views里面并不复杂,只需要实现hook_views_data即可;如果要修改其它模块的hook_views_data,则可以使用hook_views_data_alter。