Slow chậm Thêm một mặt hàng khác với các trường có giá trị không giới hạn


8

Trong Drupal 7, khi bạn có nút có trường có giá trị không giới hạn (giả sử, trường hình ảnh), thời gian phản hồi "thêm một mục khác" sẽ trở nên rất chậm sau khi bạn thêm 10 - 20 mục. Làm thế nào để bạn chống lại vấn đề này? Bạn đã bao giờ gặp phải vấn đề này?

Tôi đã tạo một dự án, trong đó người dùng có thể thêm tối đa 100 giá trị của trường hình ảnh mà theo lý thuyết có cài đặt giá trị không giới hạn. Nhưng, sau khi bạn thêm một tá hình ảnh, mỗi lần nhấp mới vào "Thêm mục khác" sẽ trở nên chậm hơn trước. Tôi biết điều này xảy ra vì thực tế là Drupal xây dựng lại trường này và tất cả các giá trị của nó sau mỗi yêu cầu ajax, vì vậy, càng nhiều giá trị bạn thêm vào thì Drupal phải làm nhiều hơn cho mọi yêu cầu "ajax", nhưng thực ra, đây không phải là điều khá tuyệt vời

Có cách tiếp cận nào về cách thay đổi / ghi đè một hành vi như vậy không?

Câu trả lời:


3

Dựa trên câu trả lời của Charlie, tôi thấy rằng phải mất khoảng thời gian tương tự để tải lại khối nếu bạn thêm 1 hoặc 100 mục, vì vậy đây là một mẹo để thêm danh sách chọn số trong biểu mẫu bên cạnh 'thêm thêm 'để bạn có thể chọn số lượng bạn đang thêm. Điều này tiết kiệm rất nhiều thời gian và vẫn linh hoạt. Có thể được bọc trong một mô-đun nhỏ

<?php
/**
* Implements hook_field_attach_form()
*/
function village_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode){
  $options = array('language' => field_valid_language($langcode));
  // Merge default options.
  $default_options = array(
    'default' => FALSE,
    'deleted' => FALSE,
    'language' => NULL,
  );
  $options += $default_options;
  list(, , $bundle) = entity_extract_ids($entity_type, $entity);
  $instances = _field_invoke_get_instances($entity_type, $bundle, $options);
  // Iterate through the instances.
  $return = array();
  foreach ($instances as $instance) {
    // field_info_field() is not available for deleted fields, so use
    // field_info_field_by_id().
    $field = field_info_field_by_id($instance['field_id']);
    $field_name = $field['field_name'];
    //If we are looking at our field type and specific widget type, and we are multiple entries
    if($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED){
      //Check just in case the button is here, and add another #submit function
      if(isset($form[$field['field_name']]['und']['add_more'])){
        // add a simple select list, this defaults to numb 3
        $form[$field['field_name']]['add_more_number'] = array(
          '#type' => 'select',
          '#title' => t('Add more no.'),
          '#options' => drupal_map_assoc(range(0, 50)),
          '#default_value' => 2,
        );
        $form[$field['field_name']]['und']['add_more']['#submit'][] = 'village_field_add_more_submit';
        $form[$field['field_name']]['und']['add_more']['#value'] = 'Add more rows';
      }
    }
  }
}
function village_field_add_more_submit($form, &$form_state){
  $button = $form_state['triggering_element'];
  // Go one level up in the form, to the widgets container.
  $element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -1));
  $field_name = $element['#field_name'];
  $langcode = $element['#language'];
  $parents = $element['#field_parents'];
  // Alter the number of widgets to show. items_count = 0 means 1.
  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
  //get the number from the select
  $numbtoadd = $form[$field_name]['add_more_number']['#value'];
  if($numbtoadd){
    $field_state['items_count'] += $numbtoadd;
    field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
    $form_state['rebuild'] = TRUE;
  }
}
?>

Tôi cũng đã đăng đề xuất trên Drupal.org tại https://drupal.org/node/1394184#comment-8252701 trong đó op có vấn đề tương tự.


Tôi đã điều chỉnh mã ở trên cho một trường tùy chỉnh với số lượng thẻ không giới hạn và nó hoạt động tốt với tôi. Thay đổi duy nhất tôi đã thực hiện đối với logic cốt lõi là trừ 1 từ $ numbtoadd trước khi sử dụng nó. Tôi nghĩ rằng điều này là do items_count được thể hiện quá mức vì nó dựa trên zero?
Dave Bruns

2

Đó là sự hoàn hảo từ bản chất của API biểu mẫu và cách nó làm cho toàn bộ $form$form_statekhả dụng trở lại trên máy chủ. Đây là một điều tuyệt vời vì rất nhiều lý do, mặc dù tôi đồng ý rằng nó có thể khá khó chịu từ góc độ hiệu suất. Một số thống kê trên máy chủ Ubuntu 12.04 chạy Apache2 với PHP-FPM:

  • Tôi đã thêm 30 mục vào một trường tệp, thêm và tải lên 1 mục một lần và tổng thời gian để tải lên + phản hồi của máy chủ + chèn javascript của phần tử mới đã tăng từ 414 mili giây, tăng lên trên mỗi lần tải lên liên tiếp từ 0-20 mili giây, kết thúc ở mức 800 mili giây cho chuyến đi số 30.

  • Tôi đã nhấp vào "Thêm một mục khác" cho trường văn bản không giới hạn 100 lần và tổng thời gian đã đi từ 337 mili giây lên đến 1,3 giây. Nếu hình thức của tôi phức tạp hơn, những con số này sẽ chỉ tăng lên.

Trong $form_state['fields']['your_field_name']['und']tồn tại một tài sản được gọi là items_count. Điều này được sử dụng để tính toán số lượng các widget trường sẽ được hiển thị cho một trường nhất định. Tôi khuyên bạn nên sử dụng hook_field_attach_form()để thay đổi $form_state trước khi tiện ích của trường được xây dựng và đặt thuộc tính của trường items_countthành số lớn hơn, do đó cung cấp cho bạn số lượng trường bạn cần ngay lập tức. Người dùng vẫn có thể thêm nhiều mặt hàng. Tùy thuộc vào bạn để tìm một cách tốt hơn để ẩn các mục bổ sung khỏi việc tạo mẫu dài 10 trang; có lẽ một div với overflow: scroll;có thể làm việc. Dù sao, đây có thể là điểm khởi đầu để bạn tìm thứ gì đó cho phép tiến trình công việc của bạn diễn ra nhanh hơn:

function mymodule_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
  $form_state['field']['field_my_field'][$langcode]['items_count'] = 100;
}

Chỉnh sửa: Mã mẫu thiếu một số logic để đảm bảo nó chỉ chạy cho dạng thích hợp và sẽ không cho phép bạn 'thêm một mục khác'. Tôi sẽ sửa lại điều này khi tôi có một ví dụ làm việc tốt hơn tại địa phương.


Xin chào Charlie, tôi cũng nghĩ về mánh khóe bạn mô tả, nhưng mọi thứ trở nên tồi tệ hơn, khi người dùng của bạn muốn sắp xếp lại các trường (trong trường hợp của tôi, đó là một yêu cầu quan trọng). Khi bạn cố gắng sắp xếp lại một trong 100 trường thông qua drag'n'drop, trình duyệt sẽ bị treo mãi mãi ...
Timur Kamanin

Nó chỉ treo trên các trường tập tin đặt hàng lại hoặc các trường văn bản là tốt? Điều đó có vẻ kỳ lạ, vì draggable.js không nên gửi bất cứ thứ gì trở lại máy chủ mà chỉ lắng nghe thay đổi hàng và sau đó cập nhật các trường nhập liệu ẩn. Ngoài ra, trình duyệt và phiên bản nào bạn đang gặp phải? Tôi nghĩ rằng bất cứ điều gì chúng tôi khám phá ở đây có thể hữu ích cho nhiều người dùng khác.
Charlie Schliesser

Có, nếu bạn có trường hợp sử dụng có thể lặp lại của draggable.js treo mà yêu cầu một vấn đề cốt lõi.
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.