Làm cách nào để có được entity_type và entity_id từ bất kỳ trang thực thể nào?


9

Một số trang (đường dẫn) đại diện cho một thực thể. Ví dụ:

  • Các trang tại các đường dẫn này đại diện cho một thực thể nút, entity_id (nid) là XX:
    • / nút / xx
    • / nút / xx / xóa
    • / nút / xx / chỉnh sửa
  • Trang tại đường dẫn này đại diện cho một thực thể máy chủ tìm kiếm (được xác định bởi mô-đun api tìm kiếm), entity_id (machine_name) là 'apache_solr':
    • / admin / config / search / search_api / server / apache_solr

Làm thế nào để bạn tải dữ liệu cơ bản về thực thể này (id và loại) khi hook hoặc chức năng bạn đang ở không trao nó cho bạn?

Cách tiêu chuẩn để có được thực thể hiện tại rõ ràng là sử dụng menu_get_object($entity_type,$position_of_id_in_url) . Tuy nhiên, điều này giả định rằng bạn đang mã hóa chỉ một loại thực thể: bạn cần nêu rõ loại thực thể theo chương trình, và thậm chí tệ hơn, con người cần nghiên cứu và mã cứng ở vị trí url của id thực thể mà thực thể này sử dụng .

Gần nhất tôi có thể tìm thấy cho đến nay là lấy uri hệ thống cơ bản cho trang (ví dụ substr(request_uri(),strlen($base_path))), sau đó viết một danh sách chuyển đổi quái dị dựa trên một cái gì đó như gợi ý này , đoán và sau đó là các trường hợp mã hóa cứng cho mọi thực thể có thể bạn nghĩ rằng một trang web có thể có . Nhưng phải có một cái gì đó tốt hơn thế, phải không?

Mặc dù giải pháp chung từ cốt lõi sẽ là tốt nhất, tôi cũng sẽ chấp nhận câu trả lời phụ thuộc vào các mô-đun phổ biến như ctools (trình quản lý trang, ngữ cảnh, v.v.), API thực thể , Devel , v.v.

Nhu cầu trước mắt của tôi là các biểu mẫu chỉnh sửa, bên trong hook_field_widget_form(), đối với một tiện ích có thể (với cấu hình và mô-đun phù hợp) được đính kèm với bất kỳ loại thực thể có thể thực hiện được. Vì vậy, trong khi một giải pháp chung là tốt nhất, tôi cũng sẽ chấp nhận một câu trả lời hẹp chỉ hoạt động trong hàm này hoặc dưới dạng (Id và dữ liệu dành riêng cho loại thực thể dường như bị chôn vùi dưới dạng $, nhưng được khóa trong một thực thể gõ cách cụ thể, vì vậy việc đưa nó ra khỏi dạng $ có vẻ giống như vấn đề về gà và trứng).

------------ BIÊN TẬP ------------------

Có vẻ một số người gặp khó khăn trong việc hiểu vấn đề chung đơn giản. Đây là trường hợp sử dụng thay thế (một vấn đề khác nhưng có liên quan tôi đang gặp phải). Giả sử bạn có một khung nhìn liệt kê một số thực thể. Chế độ xem này nằm dưới dạng một khối / khung trên các trang có thể đại diện cho một thực thể, chẳng hạn như trang nút hoặc hồ sơ người dùng (hoặc cả hai). Bạn đã có một hook được thiết lập để đọc dữ liệu lượt xem và xem qua kết quả ( foreach $view->result as...). Hãy nói rằng đó là hook_view_pre numnder, có nghĩa là bạn chỉ có đối tượng $ view. Bạn muốn làm một cái gì đó (giả sử, xóa hàng hoặc thay đổi một số dữ liệu trường) nếu hàng kết quả xem có cùng loại id thực thể và loại thực thể như trang. Bạn đã có logic để trích xuất dữ liệu này từ kết quả xem, vì vậy tất cả những gì bạn cần là tìm kiếm entity_type và entity_id của trang đang được tạo để so sánh. Dữ liệu đó ở Drupal ở đâu đó. Nếu không, Drupal không thể hiểu rằng cần phải tải chế độ xem này. Vậy làm thế nào để bạn có được nó khi nó không được chuyển đến hook hoặc chức năng bạn đang ở?


Như được chỉ ra bởi paul-m, "trang thực thể" là gì?
Letharion

Ý tôi là một tài liệu html được phân phối http được hiển thị trong trình duyệt (hoặc "trang web", có lẽ "đường dẫn" là thuật ngữ Drupal nhiều hơn?) Trên trang web Drupal [chèn thuật ngữ Drupal chính xác ở đây] đại diện và nằm trên đường dẫn của một thực thể . Ví dụ: / node / xx 'đại diện cho' một thực thể nút với id xx, như do / node / xx / xóa / node / xx / edit, / admin / config / search / search_api / server / apache_solr đại diện cho một thực thể máy chủ tìm kiếm được xác định bởi search_api mô-đun với tên máy 'apache_solr'
user56reinstatemonica8

Câu trả lời:


4

Trong Drupal Core, bạn không thể làm điều này. Vấn đề liên quan để thêm chức năng như vậy là ở đây .

Những gì cốt lõi tự làm là luôn luôn đi qua hai đối số:

function($entity, $entity_type)

Ôi Chúa ơi ... một trong những cuộc tranh luận cốt lõi của Drupal đã diễn ra trong hơn một năm ... Mặc dù vậy, câu hỏi nhanh, để vấn đề đó có liên quan, tôi phải có $ obejct. Làm thế nào bạn đề nghị tôi có được đối tượng $ entity? Có một cách chung chung?
user56reinstatemonica8

1
Nếu có cách để có được đối tượng $ entity, tôi có thể sử dụng bản hack xấu xí nhưng khả thi này từ cuộc tranh luận mà bạn đã liên kết với drupal.org/node/1042822#comment-5134730 và giải quyết vấn đề. Nhưng trước tiên tôi cần đối tượng $ entity ...
user56reinstatemonica8

4

Cách đơn giản nhất mà tôi đã tìm thấy để giải quyết vấn đề này là thực hiện hook_entity_load().

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

Sau đó, đối tượng được trả về menu_get_object()sẽ có một entity_type liên kết với nó.


4

Tôi đã phát hiện ra một cái gì đó hoạt động như thế này trong mô-đun Bộ lọc mã thông báo (phiên bản 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;
      }  
    } 

Khá thông minh - nó chỉ ra một hàm phải xảy ra trước khi hàm của nó được gọi sẽ chứa $ entity_type và $ entity ($ entity_id cũng sẽ hoạt động thay vì $ entity) và nhìn lại đối tượng backtrace cho đến khi tìm thấy nó.

Bộ lọc mã thông báo là một mô-đun xử lý trường, do đó, nó sẽ biết rằng chức năng của nó sẽ luôn được gọi sau khi gọi đến field_attach_view () . Tôi không biết nếu có một giải pháp thay thế chung chung cho field_attach_view - nhưng cách tiếp cận chung dường như có hiệu quả và luôn có thể tìm thấy một ứng viên cụ thể cho từng trường hợp cụ thể bằng cách bỏ một số mã gỡ lỗi backtrace (trước đây đã sửa lỗi liên kết) trong mã nơi bạn cần lấy thực thể và xem những gì có sẵn (sau đó kiểm tra logic và kiểm tra để đảm bảo nó luôn hiện diện).


1
Hack đẹp, thực sự hữu ích
Clive

1
Upvote chỉ vì đó là tuyệt vời. Hacky như địa ngục, nhưng tuyệt vời.
tobynew 27/07/17

Downvote vì lý do tương tự: hacky như địa ngục.
Eric MORAND

1

Các công việc sau đây để tôi nhận loại thực thể và loại thực thể theo đường dẫn:

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

0

điều này có thể giúp gì không

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

1
Chức năng của bạn dường như phức tạp và thiếu tài liệu và không tự giải thích các biến không giúp ích nhiều để hiểu rõ hơn về nó. Dù sao, sau khi tôi tìm thấy một giải pháp sử dụng menu_get_item (), tôi đã thấy, đó là bằng cách nào đó cũng có trong mã của bạn - xem câu trả lời với function custom_module_get_entity_and_entity_type_by_path(). Tôi tự hỏi trong trường hợp nào giải pháp của tôi sẽ không hoạt động, vì bạn sẽ làm nhiều thứ hơn để tìm thực thể_type.
LarS

thực sự tôi không nhớ những gì đã xảy ra với chức năng của bạn, nhưng chắc chắn tôi đã thử nó trước khi viết một cái. Trong trường hợp của tôi, tôi cần nó có một bó thực thể, loại thực thể và giá trị khóa thực thể để xử lý theo chủ đề mô-đun in, sử dụng các mẫu tùy chỉnh cho các thực thể tùy chỉnh như $ biến này ['theme_hook_suggestions'] [] = "print __ {$ định dạng} __ {$ ent ['type']} __ {$ ent ['bundle']} __ {$ nid} ";
Mykola Mykolayovich Dolynskyi

1
Không có gì sai với chức năng của tôi vì nó không có ở đó, tôi đã đăng nó một tuần trước. Bây giờ tôi thấy, bạn cũng cần tên gói, có thể đó là lý do tại sao nó phức tạp hơn.
LarS

:-D Thật vậy tuần trước. Dù sao tôi đã thử các giải pháp khác trước khi viết của riêng tôi. Có, gói, id thực thể, loại thực thể được yêu cầu trong trường hợp của tôi để tìm mẫu tùy chỉnh trang enity thích hợp thông qua $
suggest

-1

Câu trả lời thực sự cho câu hỏi này phụ thuộc vào lý do tại sao bạn cần dữ liệu và ở lớp bánh API nào bạn đang vận hành.

Nếu bạn muốn thực thể cho một trang, bạn không thể làm điều đó. Một trang nhất định có thể có nhiều thực thể trên đó. (Mọi nút, bình luận, phân loại ... đều là các thực thể.)

Nếu bạn đang sử dụng hook_field_widget_form(), thì bạn đang triển khai một trường trong API trường và câu trả lời của bạn nằm trong tài liệu : Loại thực thể là $element['#entity_type']và bạn không thể lấy ID thực thể, vì các trường triển khai API không nên tự quan tâm với.

Vậy: Tại sao bạn cần id thực thể?


Cảm ơn mẹo về phần tử $ và thật bất ngờ khi thấy trang tài liệu liệt kê các khóa của một trong các tham số. Tôi đã giả sử nếu loại thực thể mà biểu mẫu không phải là $ form hoặc $ dụ thì nó sẽ không nằm trong một phần tử của một thể hiện trên một biểu mẫu. Tất nhiên, ý tôi là trang theo nghĩa chung của tài liệu html được phân phối http trong trình duyệt, không phải là gói nút Drupal, rõ ràng sẽ là một nút. Tôi cần id thực thể cho một tiện ích liên quan đến các mối quan hệ từ mô đun Quan hệ và cần tìm ra điểm cuối nào trong mối quan hệ là thực thể 'này'. Hay nói chung hơn ...
user56reinstatemonica8

... một hàm có thể được gọi trong khi hiển thị một 'trang' chỉ đại diện cho một thực thể, xuất ra dữ liệu tham chiếu các thực thể và cần so sánh dữ liệu mà nó đang xử lý với dữ liệu trong thực thể của 'trang' sẽ được in trên.
user56reinstatemonica8

À, nếu " trang " bạn có nghĩa là trang quản lý trang, có thể có nhiều thực thể trong các bảng khác nhau, tôi chỉ nghĩ đến những trang đó trên đường dẫn của một thực thể cụ thể. Chúng có thể tải bất kỳ số lượng thực thể nào, nhưng vẫn sẽ 'đại diện' cho một thực thể mà chúng đang trên đường.
user56reinstatemonica8

Tôi muốn đặt mô-đun Relation đã thực hiện công việc nặng nhọc cho bạn: drupal.org/project/relation
paul-m

Tôi đang sử dụng mô-đun Relation, như đã nêu trong nhận xét đầu tiên của tôi và nó cung cấp cho tôi tất cả dữ liệu tôi cần về mối quan hệ. Phần đó ổn, đó không phải là vấn đề của tôi. Tôi chỉ muốn tra cứu thực thể mà đường dẫn này đại diện và đối tượng biểu mẫu, trường và widget này là để tôi có thể so sánh dữ liệu về thực thể với dữ liệu tôi có về mối quan hệ. Drupal đã phân tích đường dẫn truy vấn uri và từ đó xác định một loại thực thể và xác định một id thực thể, vì vậy tôi hy vọng nó sẽ là một nhiệm vụ tầm thường để tìm kiếm điều này. Tuy nhiên, dường như không có cách chung nào để làm điều này.
user56reinstatemonica8
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.