web-dev-qa-db-ja.com

Dbに送信されるadd_actionによる値の変更

私は今何時間もこの問題に苦しんでいます、何が起こっているかはdbに値を挿入する前のどこかで、このアクションが呼ばれているということです。

do_action_ref_array('h5p_alter_user_result', array(&$data, $result_id, $content_id, $user_id));

次に示すのは、値とその設定方法です。

$user_id = get_current_user_id();
    $result_id = $wpdb->get_var($wpdb->prepare(
        "SELECT id
        FROM {$wpdb->prefix}h5p_results
        WHERE user_id = %d
        AND content_id = %d",
        $user_id,
        $content_id
    ));

$table = $wpdb->prefix . 'h5p_results';
$data = array(
  'score' => filter_input(INPUT_POST, 'score', FILTER_VALIDATE_INT),
  'max_score' => filter_input(INPUT_POST, 'maxScore', FILTER_VALIDATE_INT),
  'opened' => filter_input(INPUT_POST, 'opened', FILTER_VALIDATE_INT),
  'finished' => filter_input(INPUT_POST, 'finished', FILTER_VALIDATE_INT),
  'time' => filter_input(INPUT_POST, 'time', FILTER_VALIDATE_INT)
);
if ($data['time'] === NULL) {
  $data['time'] = 0;
}
$format = array(
  '%d',
  '%d',
  '%d',
  '%d',
  '%d'
);

$content_id = 1;

私がやろうとしているのは、データベースに保存される前にこれらの値を変更したいということです(そしてこのフックはデータベースに保存される前に呼び出されます)。

add_action( 'h5p_alter_user_result',           'diff_test_callback' );

function diff_test_callback($args)
{
    global $wpdb;
  $user_id = 1;
    $result_id = 1;
$content_id = 1;
    $table = $wpdb->prefix . 'h5p_results';
    $data = array(
      'score' => 777,
      'max_score' => 189,
      'opened' => 333,
      'finished' => 222,
      'time' => 111
    );
    if ($data['time'] === NULL) {
      $data['time'] = 0;
    }
    $args = array( $data, $result_id, $content_id, $user_id );
    return $args;
}

しかし、値は変更されていません、何か問題がありますか?

2
hede

フックを使用して変数を修正する正しい方法

フックを使用して変数または任意の値を変更したい場合は、(アクションフックの代わりに)フィルタフックを使用してそれを行うのが最善です。内部的にはアクションとフィルタの実装はほぼ同じですが、規約は次のとおりです。

  1. アクションフックでは、コールバック関数の中で何かをしたり、エコー出力したりしますが、何も返しませんし、そのコールバック関数の範囲外の引数も変更しません。

  2. フィルタフックを使用すると、コールバック関数から値を返し、それをどこかで使用するか、またはコールバック関数の外部の変数に割り当てることができます。

そのため、apply_filters CODEを次のように使用してください。

// using apply_filters() instead of the following do_action_ref_array() line
// do_action_ref_array( 'h5p_alter_user_result', array( &$data, $result_id, $content_id, $user_id ) );
$data = apply_filters( 'h5p_alter_user_result', $data, $result_id, $content_id, $user_id );

これと一致させるには、add_filterと次のようなコールバック関数を使用します。

// Declare number of parameters to be passed in add_filter.
// According to our apply_filters() call,
// we expect 4 parameters to be passed to the callback function
add_filter( 'h5p_alter_user_result', 'diff_test_callback', 10, 4 );
function diff_test_callback( $data, $result_id, $content_id, $user_id ) {
    // do something with $data
    // remember: manipulation of $data doesn't have any affect
    // outside of this function
    // So we need this return
    return $data;
}

あなたのCODEのdo_action_ref_arrayの問題:

あなたのdo_action_ref_array呼び出しから、あなたが参照として$dataを渡そうとしているように見えます:

do_action_ref_array( 'h5p_alter_user_result', array( &$data, $result_id, $content_id, $user_id ) );

ただし、PHP 5.4以降、この動作は変更されました。 do_action_ref_arrayは、引数の参照をコールバック関数に渡しません。代わりに、コピーを渡します。

また、PHP 5.4以降、参照による呼び出し時間の経過は受け付けられません。そのため、上記のコードに示すようにapply_filtersメソッドを使用するのが最善です。

はお勧めできませんが、配列内の関数パラメータとして参照ポインタを使用して実行することができます。このような:

// add_action without passing the number of parameters
add_action( 'h5p_alter_user_result', 'diff_test_callback' );
// callback function implementation with reference pointer `&`
// for parameters you are expecting with reference
function diff_test_callback( $args ) {
    // we need the reference of $data, so using & operator here.
    $data = &$args[0];
    $result_id = $args[1];
    $content_id = $args[2];
    $user_id = $args[3];

    // now making changes to $data
    // will be reflected outside the scope of this function
    // no return is necessary
}

// at the time of executing the action,
// create the $args array with reference to $data
$args = array( &$data, $result_id, $content_id, $user_id );
do_action_ref_array( 'h5p_alter_user_result', array( $args ) );

警告:繰り返しますが、do_action_ref_arrayメソッドは注意深く参照を処理すれば機能しますが、このシナリオではfilter hookメソッドを使用することを強く推奨します。

1
Fayaz