0

我正在尝试学习编写drupal模块并正在编写一个简单的数学模块http://nodeone.se/en/the-math-question-module

我的 GUI 很好,但实际数学似乎有问题。我似乎从来没有得到正确的答案,因为我认为它会在检查当前答案之前加载一组新问题。

这是我到目前为止所拥有的:

   <?php

/**
 * @file
 * Tests users on their math skills through a series of question and answers
 */

/**
 * Implements hook_menu().
 */
function math_question_menu() {
  // add new navigation menu item
  $items['math_question'] = array(
    'title' =>  'Math questions',
    'description' => 'Test you math skills with these questions.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('math_question_page'),
    'access callback' => 'user_access',
    'access arguments' => array('administer_site_configuration'),
  );
  return $items; 
}
  $val1 = rand(1,10);
  $val2 = rand(1,10);
  variable_set('val1', $val1);
  variable_set('val2', $val2);
/**
 * Builds the form for configuring Math Questions.
 */
function math_question_page() {
  global $user;
  $num1 = variable_get('val1');
  $num2 = variable_get('val2');
  $total = $num1 + $num2;
  variable_set('total',$total);
  $form['math_question'] = array(
    '#type' => 'item',
    '#markup' => 'What is ' . $num1 . ' + ' . $num2 . ', ' . 
      check_plain($user->name) . '?',
    );
  $form['answer'] = array(
    '#type' => 'textfield',
    '#title' => t('Answer'),
    );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Check my answer'),
    );
  return $form;
}

function math_question_page_validate($form, $form_state) {
  if (empty($form['answer']['#value'])) {
     form_error($form['answer'], t('This field is required.'));
   }
   if ($form['answer']['#value'] == 
      variable_get('total')) {
    $msg = t('Good job!');
    $type = 'status';
  } 
  else {
    $msg = t('Try again...');
    $type = 'error';
  }
  drupal_set_message(check_plain($msg), $type);
}

修改代码:。.

    /**
     * Builds the form for configuring Math Questions.
     */
   function math_question_page() {
      global $user;
        $val1 = rand(1,10);
        $val2 = rand(1,10);
       $total = $val1 + $val2;
      $form['math_question'] = array(
        '#type' => 'item',
        '#markup' => 'What is ' . $val1 . ' + ' . $val2 . ', ' . 
          check_plain($user->name) . '?',
        );
      $form['answer'] = array(
        '#type' => 'textfield',
        '#title' => t('Answer'),
        );
      $form['total'] = array(
        '#type' => 'hidden',
        '#value' => $total,
        );
      $form['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Check my answer'),
        );
      return $form;
    }

    function math_question_page_validate($form, $form_state) {
      if (empty($form['answer']['#value'])) {
         form_error($form['answer'], t('This field is required.'));
       }
       if ($form['answer']['#value'] == 
          $form['total']['#value']) {
        $msg = t('Good job!');
        $type = 'status';
      } 
      else {
       $msg = t('Try again...');
       $type = 'error';
      }
      drupal_set_message(check_plain($msg), $type);
    }
4

4 回答 4

2

表单提交后 Drupal 重定向,因此您的表单字段(连同您的表单)在调用验证之前重新创建。请参阅另一个问题中的详细信息。

您的表单是使用 math_question_page 创建的,它不接受任何 form_state 参数。如果你有 form_state,那么你可以检测到 math_question_page 还没有提交,并且只保留最后一次调用的状态(最后一个随机值)。

为了使用 form_state 参数调用 math_question_page,您可以在菜单中使用drupal_build_form而不是 drupal_get_form。

于 2013-03-09T08:50:23.503 回答
2

在验证函数math_question_page_validate()中,您应该从 $form_state 变量而不是 $form 访问值。

例如:

if (!$form_state['values']['answer'] == $form_state['values']['total']) {
    form_set_error('answer', $error);
}

您还可以将答案存储在 $form_state 变量中以将其传递给验证函数(无需将值存储在 $form 中)。如果将其存储为 $form_state['total'],则可以以相同的方式访问它(如下所示)。

if (!$form_state['total'] == $form_state['values']['answer']) {form_set_error('answer', $error);}

非常感谢papirrin教授这个

我建议使用 variable_get() 来保证正确答案的安全。您保留在表单中的随机值将无法在表单重新生成后继续存在。

我的工作代码在这里。

/**
* Builds the form for configuring Math Questions.
*/
function math_question_page($form, &$form_state) {
  global $user;
    $val1 = rand(1,10);
    $val2 = rand(1,10);
    $total = $val1 + $val2;
    // Store the correct answer safely away from this form
  if (!variable_get('math_question_answer',FALSE)) {
    variable_set('math_question_answer', $total);
  }
  $form['math_question'] = array(
    '#type' => 'item',
    '#markup' => 'What is ' . $val1 . ' + ' . $val2 . ', ' . 
      check_plain($user->name) . '?',
    );
  $form['answer'] = array(
    '#type' => 'textfield',
    '#title' => t('Answer'),
    );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Check my answer'),
    );
  $form_state['redirect'] = FALSE;
  return $form;
}

function math_question_page_submit($form, &$form_state) {
  if (empty($form['answer']['#value'])) {
     form_set_error('answer', t('This field is required.'));
  } 
  else {
    if ($form_state['values']['answer'] == variable_get('math_question_answer')) {
      $msg = t('Good job!');
      $type = 'status';
    } 
    else {
      $msg = t('Try again...');
      $type = 'error';
    }
    drupal_set_message(check_plain($msg), $type);
  }
  variable_del('math_question_answer');
}
于 2013-03-08T19:31:53.703 回答
0

我也在学习编写 drupal 模块(两周前开始教程系列)。我试图做同样的模块,我认为在数据库中保存随机值的实现是不正确的。练习中问的第一件事是:

  1. 任何访问 /question 路径的用户都会得到一个简单的加两个数字的问题,例如“什么是 4 + 9?”。

因此页面的访问参数应该是“访问参数”=> 数组(“访问内容”)而不是“访问参数”=> 数组(“administer_site_configuration”)。

这会带来以下问题:如果有 2 个(或更多)用户同时浏览此页面,最新用户将覆盖数据库中的值,因此其他用户将无法完成“问题”,因为他的答案将不等于数据库中的答案。在这种情况下,将值保存到数据库不是一种选择......

同时我试图让它在没有数据库的情况下工作,但我的情况与这个问题的起始者相同,当我提交表单时,表单会覆盖值(因此,由于答案错误而引发错误)。

如果我能完成它,我会在此处发布代码,或者如果其他人在没有 variable_set() 和 variable_get() 的情况下设法完成它,我请他们在此处发布代码:)

于 2014-09-11T08:26:32.550 回答
0

不要将 $total 存储在全局变量“total”中,而是尝试将其存储为表单上的隐藏字段(除非您担心用户作弊)。你可以写:

'#type' => '隐藏,

创建一个隐藏的“总计”字段,然后在验证中检查该值,以防止总计被覆盖。

于 2013-03-08T06:52:06.937 回答