web-dev-qa-db-ja.com

すべてのノードで指定されたフィールドの値を確認するにはどうすればよいですか?

最小限のDrupalおよびPHPの経験...

問題

1つの定義済みフィールドタイプ( 'faceman')を持つコンテンツタイプ( 'hannibal')の自動作成機能があります。コンテンツタイプ「hannibal」が作成されると、別のコンテンツタイプからフィールド「murdock」の値を渡すことにより、ルールによって自動的に行われます。 'murdock'と 'faceman'は同じ値である場合があります(これらは同じ形式です:テキスト、同じフォーマット、直接コピー)。

タイプ「hannibal」の他のすべてのノードをチェックして、「faceman」の値がそのフィールドにすでに存在するかどうかを確認する必要があります。 Unique Fieldモジュールをアクティブにしていますが、ノードはルールによって作成されているため、この場合は機能しません(おそらく、ユーザーが入力したフォームでのみ機能します)。

Issue:タイプ「hannibal」のすべてのノードで、入力されている値のフィールド「faceman」を確認する方法。

私はすでにこれについてたくさんのオプションを試しました:

ルール-条件を設定しようとしましたが、「hannibal」タイプのすべてのノードをロードしてそのフィールド値をチェックする方法が見つかりません。 PHP他の場所から取得したスニペットを使用してそれを実行しようとしましたが、うまくいきませんでした。ルールコンポーネントも設定しようとしましたが、意味がありませんでした。

データベースクエリ-SQLiteを使用しています。チェックするテーブルを特定し、EntityFieldQueryを試しましたが、条件として試みたコードがページをクラッシュさせているだけです。

$value = token_replace('[node:field_murdock]', array('node' => $node));

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'source')
  ->propertyCondition('status', NODE_PUBLISHED)
  ->fieldCondition('faceman', 'faceman_value', '$value',)

$result = $query->execute();
if (isset($result['node'])) {
  return TRUE;
} 

ノードを自動的に作成し、field_facemanの既存の値と同じ値の新しいノードが作成されるのを防ぐことができる限り、(理由の範囲内で!)その方法については気になりません。

これはそのような基本的な機能(データベース内の特定のフィールドのすべての値をチェックする)のようですが、これを行う簡単な方法が欠けているに違いありません。正しい?

何か助けは?

更新と解決策

最終的にはEntityFieldQueryで解決することができました。私はこの問題を抱える唯一の人物ではあり得ないと確信しているので、将来同じ位置にいる私のスキルレベルの周りの人のために:

解決策は、PHP conditional。

ルールのトリガーは、コンテンツの保存イベントです。条件1は「コンテンツに 'faceman'フィールドがあります」です。条件2は、カスタムの実行PHP以下のとおりです。2つの条件間のリンクはありません-AND関数を試行すると、それらが破損しました。

カスタムPHPコード:

// display murdock field taken from saved content as plaintext

$value = token_replace('[node:field_murdock]');

// search database for identical values of field faceman

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'hannibal')
->propertyCondition('status', 1)
->fieldCondition('field_faceman', 'value', $value, '=')
;

// if identical value of field faceman is found, return FALSE to Rules condition

$result = $query->execute();
if (isset($result['node'])) {
return FALSE;
}
else {
return TRUE;
}

したがって、ルールのアクション部分は、値が別のノードのどこかにあるFacemanフィールドにまだ存在していない場合にのみ実行されます。既存のノードタイプハンニバルに同等の値/フォーマットのフィールドFacemanがある限り、重複ノードは作成されません。

次に、アクションルールは、ルールをトリガーした保存されたコンテンツからフィールドMurdockを直接コピーして、新しいコンテンツにFacemanフィールドを作成します。これにより、上記のロジックが機能し、Facemanは常にMurdockフィールドの子&コピーになるため、ノードは一度だけ作成する必要があります。

3
Sarastro

以下でさらに詳しく説明するように、 RulesViews Bulk Operations モジュールと組み合わせて使用​​することで、これを機能させることができます。

以下では、フィールドのマシン名がfield_optionlistであると想定しています(適切なものに変更してください)。

手順1-VBOビューを作成する

Views Bulk Operations(VBO) モジュールを使用して、関連するすべてのノードのビューを作成します。

  1. それにVBOフィールドを追加します。
  2. 値が一意であることを確認するfield_optionlistフィールドのコンテキストフィルターを追加します。 this answer から " 現在のユーザーが送信したノードをカウントするフィールドを取得する方法は? "( Niall Murphy 、merci!へのクレジット。

各ノードにnidのようなフィールドを含めます(他のフィールドは必要ありません)。考慮したいノードごとに正確に1行を取得するようにしてください。

このようなVBOビューのエクスポートは次のとおりです。

$view = new view();
$view->name = 'relevant_nodes';
$view->description = 'Produce a list of node ids that satisfy a specific filter';
$view->tag = 'default';
$view->base_table = 'node';
$view->human_name = 'Relevant nodes';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */

/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['title'] = 'Relevant nodes';
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['access']['type'] = 'perm';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['pager']['type'] = 'full';
$handler->display->display_options['pager']['options']['items_per_page'] = '10';
$handler->display->display_options['style_plugin'] = 'table';
$handler->display->display_options['style_options']['columns'] = array(
  'title' => 'title',
);
$handler->display->display_options['style_options']['default'] = '-1';
$handler->display->display_options['style_options']['info'] = array(
  'title' => array(
    'sortable' => 0,
    'default_sort_order' => 'asc',
    'align' => '',
    'separator' => '',
    'empty_column' => 0,
  ),
);
/* Field: Content: Nid */
$handler->display->display_options['fields']['nid']['id'] = 'nid';
$handler->display->display_options['fields']['nid']['table'] = 'node';
$handler->display->display_options['fields']['nid']['field'] = 'nid';
/* Field: Content: Title */
$handler->display->display_options['fields']['title']['id'] = 'title';
$handler->display->display_options['fields']['title']['table'] = 'node';
$handler->display->display_options['fields']['title']['field'] = 'title';
$handler->display->display_options['fields']['title']['label'] = '';
$handler->display->display_options['fields']['title']['alter']['Word_boundary'] = FALSE;
$handler->display->display_options['fields']['title']['alter']['Ellipsis'] = FALSE;
/* Field: Content: OptionList */
$handler->display->display_options['fields']['field_optionlist']['id'] = 'field_optionlist';
$handler->display->display_options['fields']['field_optionlist']['table'] = 'field_data_field_optionlist';
$handler->display->display_options['fields']['field_optionlist']['field'] = 'field_optionlist';
/* Field: Bulk operations: Content */
$handler->display->display_options['fields']['views_bulk_operations']['id'] = 'views_bulk_operations';
$handler->display->display_options['fields']['views_bulk_operations']['table'] = 'node';
$handler->display->display_options['fields']['views_bulk_operations']['field'] = 'views_bulk_operations';
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['display_type'] = '0';
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['enable_select_all_pages'] = 1;
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['row_clickable'] = 1;
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['force_single'] = 0;
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['entity_load_capacity'] = '10';
/* Contextual filter: Content: OptionList (field_optionlist) */
$handler->display->display_options['arguments']['field_optionlist_value']['id'] = 'field_optionlist_value';
$handler->display->display_options['arguments']['field_optionlist_value']['table'] = 'field_data_field_optionlist';
$handler->display->display_options['arguments']['field_optionlist_value']['field'] = 'field_optionlist_value';
$handler->display->display_options['arguments']['field_optionlist_value']['default_action'] = 'default';
$handler->display->display_options['arguments']['field_optionlist_value']['default_argument_type'] = 'raw';
$handler->display->display_options['arguments']['field_optionlist_value']['default_argument_options']['index'] = '0';
$handler->display->display_options['arguments']['field_optionlist_value']['summary']['number_of_records'] = '0';
$handler->display->display_options['arguments']['field_optionlist_value']['summary']['format'] = 'default_summary';
$handler->display->display_options['arguments']['field_optionlist_value']['summary_options']['items_per_page'] = '25';
$handler->display->display_options['arguments']['field_optionlist_value']['limit'] = '0';
/* Filter criterion: Content: Published */
$handler->display->display_options['filters']['status']['id'] = 'status';
$handler->display->display_options['filters']['status']['table'] = 'node';
$handler->display->display_options['filters']['status']['field'] = 'status';
$handler->display->display_options['filters']['status']['value'] = 1;
$handler->display->display_options['filters']['status']['group'] = 1;
$handler->display->display_options['filters']['status']['expose']['operator'] = FALSE;
/* Filter criterion: Content: Type */
$handler->display->display_options['filters']['type']['id'] = 'type';
$handler->display->display_options['filters']['type']['table'] = 'node';
$handler->display->display_options['filters']['type']['field'] = 'type';
$handler->display->display_options['filters']['type']['value'] = array(
  'article' => 'article',
);

/* Display: Page */
$handler = $view->new_display('page', 'Page', 'page');
$handler->display->display_options['path'] = 'relevant-nodes';

ステップ2-ルールを作成する

次のようなルールを作成します。

  • ルールイベント:「Articleタイプのコンテンツを保存する前に」のようなものが最も適切と思われますが、適合する任意のバリエーションを使用できます。

  • ルール条件: "VBOビューから返された結果の数をチェックする"。前の手順で作成したVBOビューを選択します。その際、「ビューに渡す引数を1行に1つずつ指定するように求められます。トークンの置換パターンを使用できます。」。そこで入力されるトークンはnode:field-optionlistです。結果の数が1以上の場合、値はすでに存在しています。したがって結果の最小数内に、値1を入力する必要があります。

  • ルールアクション:これはあなた自身の想像力にかなり依存しています。たとえば、ルール条件がTRUEの場合、「データ値の設定」を使用して、そのフィールドの値を以前の値、つまりnode-unchanged:field-optionlistに復元できます。 (値をAdvancedからBasicに変更しようとした場合)などの適切なメッセージも表示する場合があります。

    値「Basic」は、少なくとも1つの他のノードですでに使用されています...(フィールド値は「Advanced」のままです)。

上記の内容を正確に実行するルールのエクスポートを次に示します(Rules UIが有効で、マシン名field_optionlistのフィールドがある場合、このルールをインポートするだけでよいはずです)。

{ "rules_prevent_multiple_nodes_with_same_field_value" : {
    "LABEL" : "Prevent multiple nodes with same field value",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "views_bulk_operations", "rules" ],
    "ON" : { "node_presave--article" : { "bundle" : "article" } },
    "IF" : [
      { "views_bulk_operations_condition_result_count" : {
          "view" : "relevant_nodes|page",
          "args" : [ "node:field-optionlist" ],
          "minimum" : "1"
        }
      }
    ],
    "DO" : [
      { "drupal_message" : {
          "message" : "The value \u0022[node:field-optionlist]\u0022 has already been used in at least 1 other node ... (field value remains \u0022[node-unchanged:field-optionlist]\u0022).",
          "type" : "error"
        }
      },
      { "data_set" : {
          "data" : [ "node:field-optionlist" ],
          "value" : [ "node-unchanged:field-optionlist" ]
        }
      }
    ]
  }
}

私のルールイベントは「記事」(適切なものに変更)に制限されており、このルールをインポートする前に、field_optionlistのマシン名をフィールドの他のマシン名に置き換えます。

完了!

2
Pierre.Vriens