web-dev-qa-db-ja.com

プログラムでリアクションルールを実行する

コマースルール「匿名注文の新しいアカウントを作成する」をコードから実行したい。 _user_save_などでユーザーを作成できますが、このルールが気に入って再利用したいと考えています。
1時間後、私はこのコードで終了しました:

_// Load reaction rule by name.
$rule = rules_config_load('commerce_checkout_new_account');
// We need $state for 'evaluate' or 'fire'.
$state = new RulesState();
// Add 'commerce_order' parameter to state.
$state->addVariable('commerce_order', $line_item_wrapper->order->value(), array('type' => 'commerce_order', 'label' => 'Commerce order'));
// Execute rule.
$rule->evaluate($state);
// How can I get created user account from $rule?
// Now I have to do user_load_by_mail().
_

それは機能しますが、それが最良の方法だとは思いません。
特にRulesStateを手動で作成したくありません。私はsetUpState()と他の多くのメソッドがあることを知っています。新しいルールコンポーネントを作成せずに、最適なソリューションを見つけたいです。

5
kalabro

関連するソリューションとして、プログラムでRulesComponentを実行する方がはるかに簡単です。それらはそのために設計されています。

たとえば、$commerce_orderパラメータを受け入れるRulesコンポーネント(タイプ "Rule")について考えてみます。

この場合、cronキューからキューに入れられた注文アイテムを処理し、APIを介して注文をリモートシステムにプッシュします。

function MODULE_queue_iwi_Push_instant_sale($item){
  try{
    if($order = commerce_order_load($item['order_id'])){
      // Invoke the rules component programmatically
      // passing the $order parameter
      rules_invoke_component('rules_iwi_Push_instant_sale', $order);
    }
  }catch(Exception $e){
    watchdog_exception('my_module', $e);
  }
}

私は、ルールコンポーネントを、呼び出すことができ、パラメーターを渡し、場合によっては値を返すことができる関数と同様に考えることが好きです。彼らは他の魔法のようなこともできます。 rules_invoke_component を参照

一方、リアクションルールはイベントドリブンであり、node_saveなどのイベントによってトリガーされ、関連するパラメーターを渡します。 rules_invoke_event を参照

ルールコンポーネントの詳細はこちら: https://drupal.org/node/1582182

5
David Thomas

答えてくれてありがとう。ここでコードを確認した後、(コンポーネントではなく)ルールを直接実行するように機能するヘルパー関数を作成しました。これは、最初のコードよりも少しシンプル/クリーンです。

UIでルールを確認し、パラメーター(条件によっては、ラップされたオブジェクトとロードされたオブジェクトがある場合があります。実験)、イベントマシンID(削除イベントURL内)、およびルールマシンID(ルール編集URL内)を把握する必要があります。

例:コマースオーダーのメールを送信します。

    $order = commerce_order_load(285);
    $params = array('commerce_order' => $order);
    $status = mysite_test_fire_rule('my_rule_machine_name', 'commerce_checkout_complete', $params);

/**
 * @param $name string Machine name of rule to fire. From UI edit url.
 * @param $event string Machine name of event. This is a protected property on rule.
 *        dpm($rule->events) or get from the delete button URL on the rule itself.
 * @param $params array of parameters to pass to function, key value paired. Name of param, value of param
 *
 * @source http://drupal.stackexchange.com/questions/45183/execute-reaction-rule-programmatically
 */
function mysite_test_fire_rule($rule_name, $event, $params){
  $rule = rules_config_load($rule_name);
  $state = new RulesState();
  foreach ($params as $param_key => $param) {
    $state->addVariable($param_key, $param, $rule->parameterInfo(TRUE)[$param_key]);
  }
  return $rule->fire($state);
}
2
Jeremy John

もっと良い方法はないと思います。コードからイベントルールを起動することは一般的ではありません。私がこれを使用して見つけた唯一の場所はコマース製品の事前計算です http://www.rit.edu/drupal/api/drupal/sites%21all%21modules%21commerce%21modules%21product_pricing%21commerce_product_pricing.module /function/commerce_product_pre_calculate_sell_prices/7.41 自分と同じRulesState()の作成

0
yogaf

個人的には、ルールではなく、チェックアウトフックで実行することを好みます。自分自身にも。

function hook_commerce_checkout_complete($order) {

        global $user;

            $customer_id = (empty($order->data['self']['CustomerID'])) ? 0 : $order->data['self']['CustomerID'];
        //Create a user if the person is anonymous
        if ($user->uid == 0) {
        //Ignore my customization here, I passed in form data from a custom form to this part, you can just as easily get access to shipping/billing entity data to do the same thing.

            $new_uid = user_creation($order->data['self']['ShippingEmailAddress'], $order->data['self']['ShippingEmailAddress'], $order->data['self']['Password'], $customer_id, $order->data['self']['FirstName'], $order->data['self']['LastName']);
            unset ($order->data['self']['CustomerID']);
            //Set the user id to the newly created user id

            $order->uid = $new_uid;
        } else {
            //Since the user is not anonymous we set the $uid to the value of the currently logged in user
            $order->uid = $user->uid;
        }
0