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

検証関数math_question_page_validate()では、$ formからではなく、$form_state変数から値にアクセスする必要があります。

例えば:

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);}

これを教えてくれてありがとうパピリン

正解を安全に保つために、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 に答える
2

Drupalはフォームの送信後にリダイレクトするため、検証が呼び出される前にフォームフィールド(フォーム全体)が再作成されます。別の質問でそれについての詳細を参照してください。

フォームはmath_question_pageで作成されますが、これはform_state引数を取りません。form_stateがある場合は、math_question_pageがまだ送信されていないことを検出し、最後の呼び出しの状態(最後のランダム値)を保持することができます。

form_state引数を指定してmath_question_pageを呼び出すには、メニューでdrupal_get_formの代わりにdrupal_build_formを使用できます

于 2013-03-09T08:50:23.503 に答える
0

$ totalをグローバル変数「total」に格納する代わりに、フォームの非表示フィールドとして格納してみてください(ユーザーの不正行為が心配な場合を除く)。あなたは書ける:

'#type' =>'非表示、

非表示の「合計」フィールドを作成し、検証でその値を確認して、合計が上書きされないようにします。

于 2013-03-08T06:52:06.937 に答える
0

私もdrupalモジュールを書くことを学んでいます(2週間前にチュートリアルシリーズを開始しました)。私はこれと同じモジュールを実行しようとしましたが、データベースにランダムな値を保存する実装は正しくないと思います。演習で最初に尋ねられるのはこれです:

  1. / questionパスにアクセスするすべてのユーザーは、「4 + 9とは何ですか?」などの単純な2つの数字の追加の質問を受け取ります。

したがって、ページのアクセス引数は、「アクセス引数」=> array('access content')ではなく「accessarguments」=> array('administer_site_configuration')である必要があります。

これには次の問題が伴います。このページを同時に閲覧しているユーザーが2人(またはそれ以上)の場合、最新のユーザーがデータベースの値を上書きするため、他のユーザーは「質問」を完了できません。彼の答えはデータベースの答えと同じではありません。この場合、データベースに値を保存することはできません...

その間、データベースなしで動作させようとしていますが、この質問のスターターと同じ状況で、フォームを送信すると値が上書きされます(つまり、答えが間違っているためにエラーがスローされます)。

私がなんとかそれを完了することができれば、私はここにコードを投稿します、または誰かがvariable_set()とvariable_get()なしでそれを完了することができたなら、私は彼らにここにコードを投稿するように頼みます:)

于 2014-09-11T08:26:32.550 に答える