欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

drupal form模板复写方法 有大用 有大大用

 有英文的 看看 /node-admin/8465

给form制作一个template

从官方的drupal api document中可得到form有#theme这个参数,它可以指定form使用一个模板来用于form的基本布局,#theme的值必须是通过hook_theme声明的key。一般情况下,即使不去声明#theme,#theme也会有一个与本form同名的默认值,所以只需要用hook_theme声明一个与form name一样的key就可以。

mymodule.module:

复制代码
function mymodule_form(){
  // ...
  return $form;
}

function mymodule_theme() {
    return array(
        // theme name与form ID一样。这是由于每个form[#theme]都有一个等于form ID的默认值。
        'mymodule_form' => array(
            'render element' => 'form',
            'template' => 'mymodule-form', // 对应文件名mymodule-form.tpl.php
        ),
    );
}
复制代码

mymodule-form.tpl.php (其它HTML代码随意):

<?php $form = $variables['form'];?>

<?php echo drupal_render($form['name']); // 'name' form element ?>

<?php echo drupal_render_children($form); // print other all form element ?>

 

可以使用hook_form_alter修改form的内容,前提是得到form ID(drupal中所有form都会有一个form ID,一般与创建form的函数名相同)
http://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_form_alter/7

以下方法可以输出所有form的form ID,得到form ID才可以对form进行单独操作,建议加到theme下的template.php中,命名为mytheme_form_alter (mytheme要改为当前theme的名字)

复制代码
function mytheme_form_alter(&$form, &$form_state, $form_id) {
  $print = '<pre>' . print_r($form, TRUE) . '</pre>';
  if (module_exists('devel')) {
    dsm($form_id); // print form ID to messages
  }
  else {
    drupal_set_message($form_id); // print form ID to messages
  }
  if (module_exists('devel')) {
    dsm($form); // pretty print array using Krumo to messages
  }
  else {
    drupal_set_message($print);  // print array to messages
  }
}
复制代码


来自  http://www.cnblogs.com/catcat811/p/3330613.html


使用 Drupal Form Hooks 进行表单自定义修改

发布:smiling 来源: PHP粉丝网  添加日期:2014-12-05 14:26:24 浏览:25 评论:0 

下面我们一起来看看使用 Drupal Form Hooks 进行表单自定义修改的具体过程,希望文章对大家会有所帮助.

Drupal使用或者开发过程中最常用到的Hooks(钩子)莫过于hook_form_alter,你所常见的Drupal网站中的内容创建,联系表单,Menu菜单,用户注册等等都会用到表单的钩子.

Drupal Form Hooks

hook_form_alter 中的hook直接替换为你的模块名称,代码如下:

  1. /** 

  2. * Implements hook_form_alter(). 

  3. */ 

  4. function custom_form_alter(&$form, &$form_state$form_id) { 

  5. switch($form_id) { 

  6. case 'user_profile_form': 

  7. //doing something 

  8. break

hook_form_FORM_ID_alter 是 hook_form_alter的一个变种,直接对某一个具体的表单进行修改,代码如下:

  1. /** 

  2. * Implements hook_form_FORM_ID_alter(). 

  3. */ 

  4. function custom_form_user_profile_form_alter(&$form, &$form_state) { 

  5. if ($form['#user_category'] == 'settings') { 

  6. if (variable_get('configurable_timezones', 1)) { 

  7. system_user_timezone($form$form_state); 

  8. return $form

通过以上2个Hooks就可以轻松给Drupal 添加自定义的表单元素,每一个form都可以自定义theme前段元素,render的elements 都会通过variables传递给主题,代码如下:

  1. /** 

  2. * Implements hook_theme(). 

  3. */ 

  4. function custom_theme() { 

  5. return array

  6. 'user_profile_form' => array

  7. 'render element' => 'form', 

  8. ), 

  9. ); 

自定义form的element样式,代码如下:

  1. function theme_user_profile_form($variables) { 

  2. $form = $variables['form']; 

  3.  

  4. $output = drupal_render($form['info']); 

  5.  

  6. $header = array(t('Factor'), t('Weight')); 

  7. foreach (element_children($form['factors']) as $key) { 

  8. $row = array(); 

  9. $row[] = $form['factors'][$key]['#title']; 

  10. $form['factors'][$key]['#title_display'] = 'invisible'; 

  11. $row[] = drupal_render($form['factors'][$key]); 

  12. $rows[] = $row

  13. //开源软件:phpfensi.com 

  14. $output .= theme('table', array('header' => $header, 'rows' => $rows)); 

  15.  

  16. $output .= drupal_render_children($form); 

  17. return $output

通过 hook_preprocess_FORM_ID 在theme form element之前修改$variables,代码如下:

  1. function custom_preprocess_user_profile_form(&$variables) { 

  2. if ($variables['form']['actions']) { 

  3. //change the button name 

  4. // add new variable to theme form 

自定义form的html元素,可以将form的theme定义一个template,注意这样会降低drupal的性能,但是换来的好处是可以自定义html,代码如下:

  1. /** 

  2. * Implements hook_theme(). 

  3. */ 

  4. function lixiphp_theme($existing$type$theme$path){ 

  5. return array

  6. 'user_profile_form' => array

  7. 'render element'=>'form', 

  8. 'template' =>'templates/form/user-profile', 

  9. ), 

  10. ); 

创建user-profile.tpl.php文件在templates/form目录下,代码如下:

  1. <?php 

  2. print drupal_render($form['form_id']); 

  3. print drupal_render($form['form_build_id']); 

  4. print drupal_render($form['form_token']); 

  5. ?> 

  6. <li class=“rows”> 

  7. <?php print drupal_render($form['actions']); ?> 

  8. </li> 

本文讲究的form自定义方法实用于Drupal6,Drupal7和Drupal8.

来自 http://www.phpfensi.com/cms/20141205/8588.html
http://www.android100.net/html/201406/12/24919.html

drupal 7 如何删除form外部默认的div?

赞成!
0
否决!

又是一个关于form的问题     - -!

修改表单加时,改得最多的是其div结构,加div很好办,可以用prefix suffix,但是想删除一些自带的div时,我遇到了问题

drupal7 的几个系统自带的表单是会有一些默认的div,如果知道其tree结构还好改,有的表单完全不知道相关元素的名字,改无从下手。

比如form下都会有一个div(没样式,没class或id)把所有元素包住,虽然不影响,但是对于强迫症来说,完全无法忍受。

还比如在user_login_block 中 '#type' => 'password' 的<input>外面会默认包着一个<div class="form-item form-type-textfield form-item-name">,对于开始写的html代码<input>外根本没有包div的人,这是何其的痛苦(我的css本来是 .login-field:focus + .login-field-icon{...},突然遇到dp生成的input外居然还有div,我以前写的几乎得重写了,欲哭无泪啊)

这个是我在user.module里改的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function ($form) {
  $form['#action'] = url(current_path(), array('query' => drupal_get_destination(), 'external' => FALSE));
  $form['#id'] = 'user-login-form';
  $form['#attributes'] = array('class' => array('login hidden'));
  $form['#validate'] = user_login_default_validators();
  $form['#submit'][] = 'user_login_submit';
  $form['name'] = array(
    '#type' => 'textfield',
    //'#title' => t('Username'),
    '#maxlength' => USERNAME_MAX_LENGTH,
    '#size' => 15,
    '#required' => TRUE,
    '#prefix' => '<div class="login-form"><div class="control-group">',
    '#attributes' =>array('class' => array('login-field'),'placeholder'=>'用户名'),
    '#suffix' => '<label class="login-field-icon" for="login-pass">&#xe007;</label></div>',
  );
  $form['pass'] = array(
    '#type' => 'password',
    //'#title' => t('Password'),
    '#size' => 15,
    '#required' => TRUE,
    '#prefix' => '<div class="control-group">',
    '#attributes' =>array('class' => array('login-field'),'placeholder'=>'密码'),
    '#suffix' => '<label class="login-field-icon" for="login-pass">&#xe00b;</label></div>',
  );
  //$form['actions'] = array('#type' => 'actions',);
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('登陆'),
    '#attributes' =>array('class' => array('lbtn lbtn-primary lbtn-large lbtn-block')),
  );
  $items = array();
  if (variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL)) {
    $items[] = l(t('用户注册'), 'user/register', array('attributes' => array('class' => array('login-link'),'title' => t('创建一个新的用户'))));
  }
  $items[] = l(t('忘记密码?'), 'user/password', array('attributes' => array('class' => array('login-link'),'title' => t('通过邮箱更新密码'))));
  $form['links'] = array(
    '#markup' => l(t('用户注册'), 'user/register', array('attributes' => array('class' => array('login-link'),'title' => t('创建一个新的用户')))).l(t('忘记密码?'), 'user/password', array('attributes' => array('class' => array('login-link'),'title' => t('通过邮箱更新密码')))),
    '#prefix' => '<div class="login-link-wrapper clearfix">',
    '#attributes' =>array('class' => array('login-link-wrapper clearfix')),
    '#suffix' => '</div></div>',
  );
  return $form;
}

这个是我想生成的结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<form class="login hidden" accept-charset="UTF-8" method="post" action="<?php print $front_page; ?>user?destination=node"><!--login-->
   <div class="login-form"><!--login-form-->
     <div class="control-group">
       <input type="text" class="login-field" value="" placeholder="用户名" id="login-name" name="name" />
       <label class="login-field-icon" for="login-name">&#xe007;</label>
     </div>
     <div class="control-group">
       <input type="password" class="login-field" value="" placeholder="密码" id="login-pass" name="pass" />
       <label class="login-field-icon" for="login-pass">&#xe00b;</label>
     </div>
     <input class="lbtn lbtn-primary lbtn-large lbtn-block" type="submit" value="登陆" name="op" />
     <input type="hidden" name="form_id" value="user_login">
     <div class="login-link-wrapper clearfix">
       <a class="login-link" href="<?php print $front_page; ?>user/register">用户注册</a>
       <a class="login-link" href="<?php print $front_page; ?>user/password">忘记密码?</a>
     </div>
   </div><!--./login-form-->
</form><!--./login-->

几乎都能实现了,就是出现了上诉的两个问题

 

3 个回答

赞成!
0
否决!

可以用 theme 优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * Implements hook_form_alter().
 */
function hook_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'user_login') {
    $form['#theme'] = array('overwrite_user_login');
  }
}
 
/**
 * Implements hook_theme().
 */
function hook_theme($existing, $type, $theme, $path){
  return array(
    'overwrite_user_login' => array(
      'render element' => 'form',
      'template' => 'form--user_login',
      'path' => $path . '/templates',
    ),
  );
}

然后增加 form--user_login.tpl.php文件

1
2
3
<?php
print drupal_render_children($form)
?>
 
赞成!
0
否决!

谢谢,这个方法是可行的!不过有没有直接修改原生的表单的方法呢?

还有用theme的方法如何打印#token和#build_id?

没有#token和#build_id对安全性有影响没有?

 
赞成!
0
否决!

以user_register表单为例:

定义一个函数

your_theme_name_ 或者 phptemplate_ 加 name_of_form($form).

 

1
2
3
4
5
6
<?php
function phptemplate_user_register($form) {
    $variables = array('user' => $user, 'form' => $form);
    return _phptemplate_callback('user_register', $variables);
}
?>

然后创建同名tpl.php , 如本例是:user_register.tpl.php

1
2
3
<?php
drupal_set_message('< pre >'. var_export($variables,TRUE) .'< /pre >');
?>

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<div id="regform1">
<fieldset class="group-account-basics collapsible"><legend>Account Basics</legend>
 
<?php print drupal_render($form['name']); ?>
 
<?php print drupal_render($form['mail']); ?>
 
<?php print drupal_render($form['pass']); ?>
 
<?php print drupal_render($form['field_user_picture']); ?>
 
<?php print drupal_render($form['field_city']); ?>
 
</fieldset>
</div>
 
<div id="regform2">
<fieldset class="group-story collapsible"><legend>My Story</legend>
 
<?php print drupal_render($form['field_storypic']); ?>
 
<?php print drupal_render($form['field_user_story_field']); ?>
 
</fieldset>
</div>
 
<?php print drupal_render($form['captcha']); ?>
 
<?php print drupal_render($form['submit']); ?>
 
<?php
unset($form['field_mostimportantlesson']);
print drupal_render($form);
?>

 



来自  http://www.drupalla.com/node/2377


drupal_get_form, 让drupal认得它是个form

form需要用drupal_get_form来加工,system才会把它认为是form,其实最终form的array也是drupal_render进行处理,drupal_get_form仅仅是给array添加让system认定为form的基本数据。

drupal_render接收的参数是一个array,它认为array嵌套的元素都是一个array,除非用#这个特殊键值声明。例如array('#markup' => '<span>....</span>');

form, form_state - form用于前后交互的变量

form的callback function都会有form和form_state两个参数,form用于生成form的结构,最终输出到页面上,form_state用于保存form的状态,并可以在callback之间转递数据。

在$form中,所有不带#开头的键名会被视为表单元素或分组元素;带#开头的键名会被视为表单元素的属性。

$form_state除了交互数据外,还有一些键名有特殊作用:

$form_state['input']
$form_state['values'] : 从form post过来的所有值
$form_state['redirect'] : 让form完成submit后自动跳转到指定页面
$form_state['rebuild']

给form制作一个template

从官方的drupal api document中可得到form有#theme这个参数,它可以指定form使用一个模板来用于form的基本布局,#theme的值必须是通过hook_theme声明的key。一般情况下,即使不去声明#theme,#theme也会有一个与本form同名的默认值,所以只需要用hook_theme声明一个与form name一样的key就可以。mymodule.module:

function mymodule_form(){
  // ...
  return $form;
}
 
function mymodule_theme() {
    return array(
        // theme name与form ID一样。这是由于每个form[#theme]都有一个等于form ID的默认值。
        'mymodule_form' => array(
            'render element' => 'form',
            'template' => 'mymodule-form', // 对应文件名mymodule-form.tpl.php
        ),
    );
}

mymodule-form.tpl.php:

<?php $form = $variables['form'];?>
 
<?php echo drupal_render($form['name']); // 'name' form element ?>
 
<?php echo drupal_render_children($form); // print other all form element ?>

修改其它form同理,先用devel确认form的#theme值,然后使用hook_theme创建对应的key。如果form已经有template,可以使用hook_form_alter把#theme修改为另外的名。

修改一个已存在的form

可以使用hook_form_alter修改form的内容,前提是得到form ID(drupal中所有form都会有一个form ID,一般与创建form的函数名相同)
Link

以下方法可以输出所有form的form ID,得到form ID才可以对form进行单独操作,建议加到theme下的template.php中,命名为mytheme_form_alter (mytheme要改为当前theme的名字)

function mytheme_form_alter(&$form, &$form_state, $form_id) {
  $print = '<pre>' . print_r($form, TRUE) . '</pre>';
  if (module_exists('devel')) {
    dsm($form_id); // print form ID to messages
  }
  else {
    drupal_set_message($form_id); // print form ID to messages
  }
  if (module_exists('devel')) {
    dsm($form); // pretty print array using Krumo to messages
  }
  else {
    drupal_set_message($print);  // print array to messages
  }
}

提取node form

function example_form($form, &$form_state, $node = NULL) {
  if (!$node) {
    $node = new stdClass();
    $node->type = 'page';
    $node->title = '';
    $node->language = LANGUAGE_NONE;
  }
  $form_state['#node'] = $node;
  field_attach_form('node', $node, $form, $form_state);
  $form['actions'] = array(
    '#type' => 'actions'
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save')
  );

  return $form;
}

function example_form_submit($form, &$form_state) {
  global $user;
  $node = $form_state['#node'];
  if(!isset($node->uid)){
    $node->uid = $user->uid;
  }
  field_attach_submit('node', $node, $form, $form_state);
  node_save($node);
}

free element, 使用传统的方法呈现element

function mymodule_form(){
  // 必须存在,否则submit无法得到chk的值
  $form['chk']= array(
    '#type' => 'hidden'
  );
  $form['html'] = array(
    '#markup' => '<input type="checkbox" name="chk[]" value="1"/>|||<input type="checkbox" name="chk[]" value="2"/>'
  );
  $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
  return $form;
}

隐藏表单元素

$form['any']['#access'] = false; // 不可见
$form['any']['#value'] = $default_value; // 强制设置value,不接受post数据

element group的form error,当form的元素层次很多时,error的处理会比较特别

一般用法:form_set_error('field_image', $message);

如果form用了多层次的element,例如$form['group'][0]['field_image'],这时需要写成:form_set_error('group][0][field_image', $message);

form element 分组

$form['parent'] = array(
    '#type' => 'fieldset',
    '#tree' => true, // 承认有子元素,否则只能取值$form_state['value']['child']
    'child' => array(
        '#type' => 'textfield'
    )
);
// 以上元素取值如下
$form_state['values']['parent']['child'];

redirect,form提交后将去到什么页面?

drupal中很常见用drupal_goto进行跳转,无论在什么地方,都会强调被跳转。但不应该用在form的validate和submit的callback中,这是因为validate和submit可以接受多个callback,如果中途被GOTO了,后台的callback就无法执行。正常的方法是使用redirect参数

$form_state['redirect'] = 'node/1';

所有form的架构、验证、提交函数,必须在.module或者显式引入外部文件

如果form function不在module引入,有可能在提交后或者AJAX后找不到对应的function

给一个form增加更多的动作

/**
 * Implementation of hook_form_alter().
 */
function mymodule_form_alter(&$form, &$form_state, $form_id){
  if($form_id == 'article_node_form')) {
    $form['actions']['submit']['#submit'][] = 'mymodule_article_node_form_submit';
  }
}

function mymodule_article_node_form_submit($form, &form_state) {
  // 表单提交后跳转到首页
  $form_state['redirect'] = 'node';
}

register a new user

// register a new user
$form_state = array();
$form_state['values']['name'] = 'robo-user';
$form_state['values']['mail'] = 'robouser@example.com';
$form_state['values']['pass'] = 'password';
$form_state['values']['op'] = t('Create new account');
drupal_execute('user_register', $form_state);


普通分类: