Drupal小记

Form API

Form元素由指定格式的数组构造,然后由渲染引擎渲染出来,
这里主要说一下比较特殊的一些表单元素 tableselect

多选的表格表单的主要结构如下:

$form['inquiry_category'] = array(
    'tableselect'=>array(
        '#type'=>'tableselect',
        // 表格的表头,包含的field1、field2、field3、field4分别表示一个单元格
        // 每一个单元的array的data键的值,为具体该单元格的内容
        '#header'=>array(
            'field1'=>array(
                'data'=>'头部表格的具体内容1'
            ),
            'field2'=>array(
                'data'=>'头部表格的具体内容2'
            ),
            'field3'=>array(
                'data'=>'头部表格的具体内容3'
            ),
            'fiel4'=>array(
                'data'=>'头部表格的具体内容4'
            ),
        ),
        // 表格的body部分
        '#options'=>array(
            // 在默认的情况下,checkbox的值为0-n的index数值
            // 当数据展示的内容为数据库表,且含有id字段时
            // 由于数据库的id并不以0开头,且id可能并不连续
            // 因此在多选表格在提交之后,提交的表单值$form_states['values']并不能确定到底是
            // 哪一个ID的结果被选中
            // 所以这里就需要将#options的每一个子数组的键统一设置为id的值,
            //避免使用0-n的顺序下标从而导致表单提交后数据库操作缺失标的而带来的一些列问题
            //如下面的例子,#options的第一个子元素为一条数据库记录, 
            //drupal默认的row1_id为0,这里我们需要将它替换成数据库中的主键,
            // 这样表单在提交之后,主键的值就会包含在$form_states['values']中,
            //下一步就可以遍历,从而更新数据库的记录。
            'row1_id'=>array(
                'field1'=>array(
                    'data'=>'row1-字段1的具体内容'
                ),
                'field2'=>array(
                    'data'=>'row1-字段2的具体内容'
                ),
                'field3'=>array(
                    'data'=>'row1-字段3的具体内容'
                ),
                'fiel4'=>array(
                    'data'=>'row1-字段4的具体内容'
                ),
            ),
        ),
        '#empty'=>'No records!',
    ),
    // 当有时候需要向表单的submit函数传递表单或是页面的参数时
    // 比较方便的方法为使用hidden隐藏字段来传至,
    //如果为前台页面,隐藏字段的值需要hash,如果是后台页面,就可以省事一点。
    // 比如,我需要知道这张table展示的具体是哪个数据库表的记录,
    //而数据库表有多个,数据库表的名字是个变量$table_name
    // 那么就可以用$table_name的值新建一个隐藏字段,
    //从而将$table_name的值添加到$form_state['values']中,
    //从而方便后面的数据库操作
    'table_name'=>array(
      '#type'=>'hidden',
      '#value'=>$table_name,
    ),
    // drupal表单的提交元素中,actions是一个wrap元素,主要用来wrap一组提交动作
    // 具体的提交动作,可以分为 submit、button、image_button
    // 其中submit为默认的表单提交原始。
    // 如果定义表单的函数名为module_name_function_name_form,
    //其中module_name为模块名,function_name为功能或是实现目的的名字,form为后缀
    // 那么默认的情况下,该表单的提交函数为module_name_function_name_form_sumbit,
    //即在表单构造函数的末尾加上'_submit'后缀,这是drupal规定的一种规范。
    // 同理,在表单构造函数的末尾加上后缀'_validate', 
    //则是该表单的提交结果验证函数,主要验证表单输入的数据是否合法
    // button或是image_button则需要制定相关的提交函数,
    //否则button在被点击之后不会执行相关的提交操作
    // 这里需要注意的是 button元素的默认属性'#executes_submit_callback'默认为FALSE,
    //即提交函数不会被执行,因此针对button或是image_button元素,还需要将
    // '#executes_submit_callback'的值设置为TRUE,
    //这样提交函数才会被调用
    // form actions还可以直接是#markup, 
    //#markup为一段html代码,多为链接,比如cancel操作,就是返回之前的页面
    // 其中l()为链接构造函数,t()文本清洁函数
    'actions' = array(
        'mark'=>array(
            '#type'=>'button',
            '#value'=>t('标记为已读'),
            '#submit'=>array('inquiry_category_tableselect_status_read'),
            '#executes_submit_callback'=>TRUE,
        ),
        'delete'=>array(
            '#type'=>'button',
            '#value'=>t('删除询盘'),
            '#submit'=>array('inquiry_category_tableselect_delete'),
            '#executes_submit_callback'=>TRUE,
        ),
        'cancel'=>array(
            '#markup'=>l(t('Cancel'), 'cancel/link/localtion'),
        ),
    ),
);

Form API – Ajax form

关于表单提交之后的操作

https://drupal.stackexchange.com/questions/37719/do-something-after-submit-the-form-at-hook-form-alter

token和form api的结合使用
https://clikfocus.com/blog/how-to-add-token-support-for-drupal-7

自定义表单的函数渲染以及与materialize主题集成
#theme
#theme-wrap

关于hook_menu

‘page arguments’ 可以接受路径为参数,但参数的格式必须为array()
例如定义一个路径 admin/manage/products/type1/12

** 路径到参数数组的转化是从0开始的 **

admin -> 0
manage -> 1
products -> 2
type1 -> 3
12 -> 4

如果需要最后一位12传递到 ‘page arguments’ 为 ‘page_callback’ 的参数
则可以这样写 ‘page arguments’=>array(4)

Renderable Array

构建renderable array之后,返回这个array作为page callback函数的结果
drupal就会自动调用系统的主题层,对array进行渲染,将array转化为html或是json数据

默认有两种组织方式

  1. 使用theme_element函数来返回回调结果,具体参照drupal api文档
    常见的有 theme_image() theme_link() theme_image_style() theme_table() theme_item_list()等等
    这些元素的多使用hook_elements()函数来进行定义。

  2. 直接返回一个数组

    直接返回一个array(),由drupal核心来选择调用哪些方法来渲染出整个array
    这里需要注意的是,返回的array必须符合相关的要求。
    根据drupal官方文档的说明,以返回table表格元素和item-list列表元素为例

    Renderable array的优势在于可以添加很多属性,调整渲染后html的结构

// 假如使用第一种方法 
$html_table_output = theme_table(
    array(
        'header'=>array(
            array('data'=>'ID'),
            array('data'=>'Name'),
            array('data'=>'Email'),
            array('data'=>'Status'),
        ),
        'rows'=>array(
            //row1
            array('data'=>array(
                array('data'=>'row1-col1-data'),
                array('data'=>'row1-col2-data'),
                array('data'=>'row1-col3-data'),
                array('data'=>'row1-col4-data')
          )),
            //row2
            array('data'=>array(
                array('data'=>'row2-col1-data'),
                array('data'=>'row2-col2-data'),
                array('data'=>'row2-col3-data'),
                array('data'=>'row2-col4-data')
          )),
        ),
    );
);

$html_table_renderable_array = array(
    '#theme'=>'table',
    '#prefix'=>'<div class='class-name'>',
    '#suffix'=>'</div>',
    '#attributes'=>array(
        'id'=>'some-id',
        'calss'=>array(
            'class-a',
            'class-b'
        ),
    ),
    '#header'=>array(
            array('data'=>'ID'),
            array('data'=>'Name'),
            array('data'=>'Email'),
            array('data'=>'Status'),
        ),
    '#rows'=>array(
        //row1
        array('data'=>array(
            array('data'=>'row1-col1-data'),
            array('data'=>'row1-col2-data'),
            array('data'=>'row1-col3-data'),
            array('data'=>'row1-col4-data'),
         )),
        //row2
        array('data'=>array(
            array('data'=>'row2-col1-data'),
            array('data'=>'row2-col2-data'),
            array('data'=>'row2-col3-data'),
            array('data'=>'row2-col4-data'),
        )),
);


$html_item_list_output = theme_item_list(
    array(
        'items'=>array(
            //如果item是字符串,这字符串就是每一个li的内容
            //如果item是array,这array的data键的值,是li的内容,其他的键则作为li标签的属性
            //这里需要注意的是class的值需要array类型
            array(
                'data'=>'item1',
                'class'=>array('list-item'),
                 ),
            array(
                'data'=>'item2',
                'class'=>array('list-item'),
                 ),
            array(
                'data'=>'item3',
                'class'=>array('list-item'),
                 ),
            array(
                'data'=>'item4',
                'class'=>array('list-item'),
                 ),
        ),
        // 列表的标题
        'title'=>array('list title'),
        // 主要的值为'ul'、'ol'
        'type'=>'ul',
        // ul的属性
        'attributes'=>array(
            'class'=>array(
                'ul-calss1',
                'ul-class2',
            ),
        'id'=>'ul-id-name',
        ),
    )
);

$html_item_list_renderable_array = array(
    '#theme'=>'item_list'
    '#items'=>array(
            //如果item是字符串,这字符串就是每一个li的内容
            //如果item是array,这array的data键的值,是li的内容,其他的键则作为li标签的属性
            array(
                'data'=>'item1',
                'class'=>'list-item',
                 ),
            array(
                'data'=>'item2',
                'class'=>'list-item',
                 ),
            array(
                'data'=>'item3',
                'class'=>'list-item',
                 ),
            array(
                'data'=>'item4',
                'class'=>'list-item',
                 ),
        ),
        // 列表的标题
    '#title'=>array('list title'),
    // 主要的值为'ul'、'ol'
    '#type'=>'ul',
    // ul的属性
    '#attributes'=>array(
        'class'=>array(
            'ul-calss1',
            'ul-class2',
        ),
        'id'=>'ul-id-name',
        ),
    ),
);


在所有theme函数需要的参数数组中的每一个键前添加’#’,并添加’#theme’键,在’#theme’键中指定相关的渲染函数,就完成了可渲染数组的构造。注意’#theme’键指定的渲染函数必须先由系统定义,或是由hook_theme()函数注册才可以。

自定义element渲染函数的主要流程为:

  • 利用hook_theme()注册element
  • 利用theme_element()创建theme_element的回调响应

注意这里的element主要是指html组件,如字段、表单元素、自定义列表等

例如,我们创建一个自定义的html组件-表单checkboxes组件的自定义渲染函数


/** * Implements hook_theme(). * 注册theme_custom_form_element_checkboxes()渲染函数到drupal的主题层中 */ function module_name_theme($existing, $type, $theme, $path) { return array( 'custom_form_element_checkboxes'=>array('render element'=>'element'), ); } function theme_custom_form_element_checkboxes($variables){ // do something here // 将处理后的结果$output作为响应返回 return $output; }