it-swarm-ja.com

エンティティページからentity_typeおよびentity_idを取得するにはどうすればよいですか?

一部のページ(パス)は1つのエンティティを表しています。例えば:

  • これらのパスにあるページは1つのノードエンティティを表し、entity_id(nid)はXX:です。
    • / node/xx
    • / node/xx/delete
    • / node/xx/edit
  • このパスのページは1つの検索サーバーエンティティ(検索APIモジュールで定義)を表し、entity_id(machine_name)は 'Apache_solr':です。
    • / admin/config/search/search_api/server/Apache_solr

現在のフックまたは関数が渡さない場合、このエンティティ(idおよびtype)に関する基本データをどのようにロードしますか?

現在のエンティティを取得する標準的な方法 明らかに使用するものmenu_get_object($entity_type,$position_of_id_in_url) 。ただし、これはエンティティタイプを1つだけコーディングすることを前提としています。エンティティタイプをプログラムで記述する必要があり、さらに悪いことに、このエンティティが使用するエンティティIDのURL位置を調査してハードコーディングする必要があります。 。

私がこれまでに見つけた最も近いものは、ページの基になるシステムuri(例:substr(request_uri(),strlen($base_path)))を取得し、次に この提案のようなもの に基づいて怪しいスイッチリストを記述し、推測してからサイトが持つ可能性があると考えられるすべてのエンティティのハードコーディングケース。しかし、それよりももっと良いものがあるに違いない。

コアからの一般的な解決策が最善ですが、 ctools (ページマネージャー、コンテキストなど)、 Entity API などの一般的なモジュールに依存する回答も受け入れます Devel など.

私の緊急の必要性は、フィールド化可能なエンティティタイプに(適切な構成とモジュールで)アタッチできるウィジェットの編集フォーム hook_field_widget_form() 内にあります。したがって、一般的な解決策が最善ですが、この関数内またはフォームでのみ機能する狭い答えも受け入れます(エンティティタイプに固有のIDおよびデータは$ formに埋め込まれているように見えますが、エンティティにキー入力されています特定の方法で入力するので、$ formから取り出すのは、鶏と卵の問題のようです)。

------------編集------------------

一部の人々は単純な一般的な問題を理解するのが難しいようです。これは別の使用例です(別の別の関連する問題が私が直面しています)。いくつかのエンティティをリストするビューがあるとします。このビューは、ノードページやユーザープロファイル(またはその両方)などの1つのエンティティを表すことができるページのブロック/ペインとして配置されます。ビューのデータを読み取り、結果を確認するフックが設定されています(foreach $view->result as...)。 hook_views_pre_render であるとしましょう。これは、$ viewオブジェクトだけを持っていることを意味します。ビューの結果行にページと同じエンティティIDとエンティティタイプがある場合は、何かを行います(たとえば、行を削除するか、フィールドデータを変更します)。ビューの結果からこのデータを抽出するためのロジックがあるので、必要なのは、生成されているページのentity_typeとentity_idを検索して比較することだけです。そのデータは、Drupalのどこかにあります。そうでない場合、Drupalは、このビューをロードする必要があることを理解できなかったでしょう。あなたがいるフックまたは関数に渡されないときにそれを取得しますか?

このように機能するものをモジュールで見つけました Token Filter (D7バージョン):

  // Attempt to fetch the entity that is being viewed via a backtrace to the
  // field_attach_view($entity_type, $entity) function and parameters §if found.
    $backtrace = debug_backtrace();
    foreach ($backtrace as $caller) {
      if ($caller['function'] == 'field_attach_view') {
        $entity_type = $caller['args'][0];
        $entity = $caller['args'][2];
        // do stuff with entity
        break;
      }  
    } 

かなり賢いです-$ entity_typeと$ entity($ entityの代わりに$ entity_idも機能します)を含む関数が呼び出される前に発生しているはずの関数を見つけ出し、それが見つかるまでバックトレースオブジェクトを調べます。

トークンフィルターはフィールド処理モジュールであるため、その関数は常に field_attach_view() の呼び出し後に呼び出されます。 field_attach_viewに代わる汎用的な代替手段があるかどうかはわかりませんが、一般的なアプローチは機能しているようで、特定のケースのケース固有の候補は、いくつかの バックトレースデバッグコード (以前は壊れたリンクの修正)エンティティを取得する必要があるコード内のポイントにアクセスし、何が利用可能かを確認します(その後、ロジックがチェックされ、常に存在することを確認します)。

Drupalコアではこれを行うことはできません。そのような機能を追加するための関連する問題は ここ です。

コア自体は常に2つの引数を渡します。

function($entity, $entity_type)
4
Letharion

この問題を解決するために私が見つけた最も簡単な方法は、 hook_entity_load() を実装することです。

_function MODULE_entity_load($entities, $entity_type) {
  foreach ($entities as $entity) {
    $entity->entity_type = $entity_type;
  }
}
_

次に、 menu_get_object() によって返されるオブジェクトには、entity_typeがバインドされます。

4
Kai

次の例は、パスによってエンティティとエンティティタイプを取得するために機能します。

/**
 * Get the entity and entity-type by path.
 *
 * @param string $path
 *   The path to the entity page.
 * @return array|boolean
 *   Contains the entity and the entity-type or false if entity or type could
 *   not be determinded.
 */
function custom_module_get_entity_and_entity_type_by_path($path) {
  $item = menu_get_item($_GET['internal_path']);
  if (empty($item['access']) || empty($item['page_arguments'][0]) || empty($item['load_functions'])) {
    return FALSE;
  }

  $entity = $item['page_arguments'][0];

  // Get entity-type.
  $load_function = reset($item['load_functions']);
  $entity_types = entity_get_info();
  dpm($entity_types);
  $entity_type = '';
  foreach ($entity_types as $type => $type_definition) {
    if ($load_function == $type_definition['load hook']) {
      // When the load_function from menu_get_item matches "load hook" of the
      // entity type definition, then the entity_type was found.
      $entity_type = $type;
      break;
    }
  }
  if (!$entity_type) {
    return FALSE;
  }

  return array('entity' => $entity, 'entity_type' => $entity_type);
}
1
LarS

これは役に立ちますか?

function entity_by_path($path) {
    $router_item = menu_get_item($path);

    $ent_sug_array = array();
    foreach ($router_item['map'] as $key => $value) {
        if(is_object($value) && isset($value->type)) {
           $ent_sug_array[$key] =  $value;
        }
    }

    $ent_sug = false;
    if(count($ent_sug_array) > 1) {
        $lf_sug = false;
        if(isset($router_item['load_functions'])) {
            if(count($router_item['load_functions']) == 1) {
                reset($router_item['load_functions']);
                $lf_sug = key($router_item['load_functions']);
            }
        }
        if($lf_sug !== false) {
            $ent_sug = is_object($router_item['map'][$lg_sug] && isset($router_item['map'][$lg_sug]->type)) ? $router_item['map'][$lg_sug] : $ent_sug;
        }
    } elseif(count($ent_sug_array) == 1) {
        $ent_sug = reset($ent_sug_array);
    }

    if(!empty($ent_sug)) {
        $bundle = $ent_sug->type;
        $ent_type = method_exists($ent_sug, 'entityType') ? $ent_sug->entityType() : false; //eck case
        if(empty($ent_type)) {
            $aclass = get_class($ent_sug);
            if($aclass == 'stdClass') {
                //node, user, core entity case
                if(isset($router_item['load_functions'])) {
                    $lf = reset($router_item['load_functions']);
                    $ei = entity_get_info();
                    foreach ($ei as $key => $value) {
                        if(empty('load hook'))
                            continue;
                        if($lf == $value['load hook']) {
                            $ent_type = $key;
                            break;
                        }
                    }
                }
            }else{
                //custom entity case
                $ent_type = $aclass;
            }
        }

        return array('entity'=>$ent_sug, 'type'=>$ent_type, 'bundle'=>$bundle);
    }

    return false;
}