Truy cập các giá trị của các loại trường không xác định khi sử dụng entity_metadata_wrapper


12

Tôi đã xem xét việc sử dụng các lớp Trình bao bọc siêu dữ liệu thực thể (được xác định bởi mô-đun thực thể trong Drupal 7) để truy cập các giá trị trường, vì đây dường như là một cách làm sạch.

Tuy nhiên, có một vài điều làm cho điều này hơi khó xử. Giả sử tôi có trình bao bọc cho loại nội dung xác định trường có tên field_somethingnhư sau:

$wrapper = entity_metadata_wrapper('node', node_load($nid));
$value = $wrapper->field_something->value();

Vấn đề đầu tiên tôi gặp phải là tôi không có cách nào biết trước được liệu tôi nhận được là giá trị thực (chuỗi, thực thể, v.v.), một trình bao bọc cấu trúc siêu dữ liệu khác (khi các trường có nhiều giá trị) hoặc một mảng (khi các trường có nhiều thuộc tính).

Tôi đã tìm ra cách để trả lời những câu hỏi đó bằng info()phương pháp:

$info = $wrapper->field_something->info();
$is_multi_value = (strpos($info['type'], 'list<') === 0);
$has_multiple_properties = isset($info['property info']]);

Tuy nhiên điều đó là khó thực tế. Bất cứ khi nào tôi muốn sử dụng một trường mà không biết định nghĩa của nó trước khi sử dụng, tôi phải tính đến một số trường hợp. Điều này làm cho mã của tôi khá nặng.

Để giải quyết vấn đề này, tôi đã viết một số mã:

  1. Đảm bảo chúng tôi luôn được trả về một mảng, ngay cả khi đó là một trường giá trị duy nhất;
  2. Khi có nhiều thuộc tính, trả về giá trị của cột đầu tiên.

Điểm 1. ở đây sẽ luôn hoạt động, trừ khi người gọi muốn biết liệu đây có phải là trường giá trị đơn hay không. Điểm 2 hoạt động trong một số trường hợp, không phải tất cả, nhưng thuận tiện khi áp dụng.

Đây là mã:

function entity_metadata_simple_values($field) {
  $fields = array();
  $values = array();
  $info = $field->info();
  if (strpos($info['type'], 'list<') === 0) {
    foreach ($field->getIterator() as $field_iteration) {
      $fields[] = $field_iteration;
    }
  } else {
    $fields[] = $field;
  }
  foreach ($fields as $final_field) {
    $ff_info = $final_field->info();
    if (isset($ff_info['property info'])) {
      $column = reset(array_keys($ff_info['property info']));
      $values[] = $final_field->{$column}->value();
    } else {
      $values[] = $final_field->value();
    }
  }

  return $values;
}

Vì vậy, câu hỏi của tôi là: có cách nào đơn giản hơn / tốt hơn để giải quyết vấn đề nhận giá trị này từ trình bao bọc siêu dữ liệu khi loại trường không được biết?

Câu trả lời:


4

Dưới đây là một vài gợi ý để làm cho quá trình này dễ dàng hơn một chút.

$wrapper->field_something->type();

sẽ trả về kiểu của các lĩnh vực, ví dụ node, taxonomy_term, integer, textvv Bạn sau đó có thể xử lý các giá trị trả về từ $wrapper->field_something->value()một cách chính xác.

Cũng thế

$wrapper->field_something->raw()

sẽ trả về giá trị thô của trường. Đó sẽ là một arraytrong trường hợp các trường có nhiều giá trị chỉ là giá trị. Chẳng hạn, một entity_referencesẽ là nid(hoặc id thực thể) của thực thể được tham chiếu hoặc một arrayid của thực thể được tham chiếu.


Ôi, tôi bước vào đó quá nhanh! Tôi muốn thêm: $ Wrapper-> field_s Something-> type () trả về cùng thông tin với phần tử 'type' của mảng được trả về bởi $ Wrapper-> field_s Something-> information (). Điều quan trọng, nó vẫn trả về một chuỗi "danh sách <type>" cho các loại đa giá trị, vì vậy tôi vẫn cần một chuỗi (hoặc tương đương) để xử lý nó đa trị (nếu tôi muốn xử lý nó trước khi tìm nạp nó).
Alice Heaton

Về điểm thứ hai: Tôi thực sự có thể tìm ra nếu nó có giá trị bằng cách kiểm tra sự trở lại của -> raw () hoặc của -> value (), tuy nhiên tôi muốn biết trước khi lấy giá trị, như thể nó có giá trị nhiều Tôi muốn chạy nó qua một vòng lặp foreach với -> getIterator () thay vì tự đi qua mảng yêu cầu tôi tạo lại một trình bao bọc cho mỗi mục.
Alice Heaton

3

Vì vậy, vì không ai đưa ra giải pháp khác, tôi sẽ trả lời câu hỏi của riêng tôi:

Không cách nào đơn giản hơn để truy cập các giá trị của các loại trường không xác định khi sử dụng trình bao bọc siêu dữ liệu thực thể.

Có các phương pháp thay thế cho phương pháp mà tôi đã mô tả ban đầu (ví dụ: những phương pháp được chỉ ra bởi @thepearson). Đặc biệt phương pháp này rất hữu ích:

 entity_property_list_extract_type($type)

Nó sẽ trả về loại được liệt kê nếu loại của bạn là một danh sách (ví dụ: 'số nguyên' nếu loại của bạn là 'danh sách <số nguyên>') hoặc sai nếu loại của bạn không phải là danh sách. Trong nội bộ, nó thực hiện một chiến lược giống như mã tôi đã đăng ban đầu, nhưng tôi đoán đó là bằng chứng trong tương lai nhiều hơn.

Kết luận là:

  • Các trình bao bọc siêu dữ liệu thực thể hoạt động tốt nếu bạn không biết về các loại trường của mình và muốn giải quyết cẩn thận từng trường hợp có thể;

  • Các trình bao bọc siêu dữ liệu thực thể hoạt động tốt nếu bạn biết chính xác các loại trường của bạn và bạn muốn sử dụng chúng;

  • Nếu bạn chỉ có một số ý tưởng về loại trường của bạn (ví dụ như tất cả văn bản, nhưng bạn không biết chúng có được định dạng hay không và bạn không biết chúng là đơn hay đa giá trị) thì trình bao bọc siêu dữ liệu của Entity không cung cấp bất kỳ lối tắt nào và bạn cần phải tự viết như tôi đã làm trong câu hỏi ban đầu.


1

Đối với kiểm tra một trường / nhiều trường, tôi thấy rất hữu ích khi kiểm tra loại đối tượng trình bao bọc, sẽ EntityListWrapperdành cho trường đa giá trị và EntityValueWrappercho trường một giá trị:

<?php
...
$wrapper = entity_metadata_wrapper('user', $account);
// Get address, or first address if a multi-value field instance.
if (get_class($wrapper->field_address) == 'EntityListWrapper') {
  $value = $wrapper->field_address[0]->value();
}
else {
  $value = $wrapper->field_address->value();
}

Hoặc thậm chíif($wrapper->field_name instanceof EntityListWrapper) {...}
rudolfbyker
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.