hook_module_implements_alter () để đặt các triển khai hook vào các tệp riêng biệt - thực tiễn xấu?


7

Trong một số mô-đun tôi đã viết, tôi sử dụng hook_module_implements_alter () để tách tệp * .module và để di chuyển các cài đặt hook thành các tệp riêng biệt.

Lý do chính là tôi cực kỳ ghét các tập tin dài. (và vâng, điều này làm tôi không hài lòng về rất nhiều tệp trong Drupal 7 và đóng góp)

Ví dụ:

Tôi biết có một vài điều cần xem xét:

  1. Nó có thể không hoạt động cho tất cả các móc. Ví dụ: khởi động hoặc cài đặt hoặc các hook không được gọi thông qua module_implements ().
  2. Điều quan trọng là bao gồm tệp tương ứng từ bên trong triển khai hook_module_implements_alter (), do cách mà module_implements () hoạt động.

Bây giờ tôi đã nghe từ một nhà phát triển Drupal lâu năm và nổi tiếng rằng thực tế này là có vấn đề. https://drupal.org/node/2230319 (bắt đầu chủ đề và nhận xét # 5 và # 11).

Trước khi tôi bắt đầu di chuyển các chức năng xung quanh, tôi muốn nghe ý kiến ​​của người khác về việc tại sao điều này là xấu, cả về mặt kỹ thuật và thẩm mỹ.

EDIT: Tôi đoán điều này có thể được chia thành hai câu hỏi:

  1. Việc chia nhỏ tệp * .module của bạn là tốt hay xấu, để các triển khai hook tồn tại ở nơi khác?
  2. Hook_module_implements_alter () có đủ tin cậy hay tôi nên sử dụng include_once __DIR__ . '/MYMODULE.filename.inc'trực tiếp trong tệp * .module? Điều gì có thể xảy ra bằng cách sử dụng hook_module_implements_alter () cho việc này?

Tôi muốn người khác cân nhắc về sự chia rẽ, nhưng tôi nghĩ nó có thể tốt. Tôi thực sự ở lý do của # 2.
mpdon Arena

(btw, một số điều trong câu trả lời là những điều tôi đã biết, nhưng điều đó vẫn có liên quan và cần thiết để làm điều này hữu ích cho những người khác. )
donquixote

Câu trả lời:


4

Tôi chỉ tìm thấy những thông tin còn thiếu.
EDIT: Và một số khác.

Sự cố với module_invoke ()

module_invoke_all()luôn gọi module_implements(), kiểm tra mô-đun bao gồm tệp bằng cách kiểm tra cả hai hook_hook_info()hook_module_implements_alter().

Tuy nhiên, module_invoke()chỉ kiểm tra hook_hook_info()không hook_module_implements_alter() .

module_invoke()được gọi là ví dụ trong _block_render_blocks()cho hook_block_view(). Điều này có nghĩa là đó hook_module_implements_alter()không phải là một giải pháp tốt để phân chia hook_block_view()việc thực hiện thành một tệp riêng biệt.

Đây là một vấn đề trong Crumbs, xem https://www.drupal.org/node/2328535 .

Đối với các hook khác, nó thường hoạt động tốt, nhưng bạn không bao giờ biết nếu một mô-đun cụ thể muốn sử dụng module_invoke()thay vì module_invoke_all().

bộ đệm module_implements () bị ô nhiễm trong bootstrap.

Một vấn đề khác là do một vấn đề cốt lõi được báo cáo ở đây:
module_implements_cache () có thể bị ô nhiễm bởi việc triển khai hook_boot () gọi module_invoke_all () trực tiếp hoặc gián tiếp

Điều này chỉ áp dụng cho các mô-đun không khởi động , trong đó có thể xảy ra việc triển khai hook_module_implements_alter()không bao giờ được phát hiện.

  1. Một chuỗi các sự kiện bất ngờ gây ra module_implements($hook)được gọi từ hook_boot().
    $hookthể là bất kỳ hook ngẫu nhiên nào, nó không cần liên quan đến mô-đun chúng tôi đang làm việc.
  2. Điều này gây ra module_implements('module_implements_alter')được gọi là.
  3. Drupal tìm kiếm tất cả các triển khai hook_module_implements_alter(). Tại thời điểm này, MODULENAME.modulechưa được bao gồm.
    Do đó, đối với phần còn lại của yêu cầu, Drupal cho rằng việc thực MODULENAME_module_implements_alter()hiện không tồn tại.
  4. Sau đó trong yêu cầu, việc triển khai các hook khác đang được phát hiện, nhưng các triển khai của MODULENAME không được tìm thấy, vì MODULENAME_module_implements_alter()không được thực thi.

Lựa chọn thay thế

Yêu cầu

Các lựa chọn thay thế đã được đề cập. Thay vì những thủ thuật này, người ta có thể bao gồm các tập tin trực tiếp. Có thể có một tác động hiệu suất nhỏ nhưng điều này có lẽ bị lu mờ bởi rất nhiều thứ khác trong Drupal.

Nhưng, thay vì sử dụng module_load_include(), tôi sẽ đề xuất một giải pháp trực tiếp hơn:

require_once __DIR__ . '/crumbs.block.inc';

Hoặc để tương thích với PHP 5.2:

require_once dirname(__FILE__) . '/crumbs.block.inc';

Tại sao không phải module_load_include ()?

Nói chung, không cần phải gọi module_load_include(), thậm chí có thể gây bất lợi, nếu tệp * .module được bao gồm từ bạn không biết (ví dụ từ settings.php) và bạn không biết nếu module_load_include()có sẵn.

Chức năng này chủ yếu ở đó để giúp bạn xác định vị trí của các mô-đun khác . Nhưng nếu bạn bao gồm trong cùng một mô-đun , thường sẽ an toàn hơn và dễ dàng hơn và nhanh hơn để làm việc với các đường dẫn tệp tương đối và rõ ràng require_once.

Gọi để trợ giúp chức năng

Như Jimajamma đã đề cập, bạn cũng có thể thực hiện hook trong *.moduletệp chính , sau đó bao gồm một tệp khác và gọi một hàm trợ giúp từ đó. Điều này được thực hiện, ví dụ như trong bộ Display.

Giải pháp này là ổn, mặc dù tôi nghĩ rằng nó vẫn đóng tập tin chính và cung cấp cho bạn nhiều nơi hơn để tìm.

Và ở đây cũng vậy, bạn có thể sử dụng allow_once thay vì module_load_include(), nếu nó nằm trong cùng một mô-đun.


Cảm ơn sự đổ vỡ chu đáo. Tôi cần một cú hích hữu ích để giúp tôi hợp nhất một nửa tá các mô-đun tùy chỉnh có liên quan nhưng riêng biệt cho một khách hàng thành một. Tôi nghĩ rằng tôi sẽ ngừng cố gắng nghĩ quá nhiều, và chỉ đơn giản là requirecác tập tin bổ sung. Một quy ước đặt tên tốt cho các tệp này cũng sẽ giúp ích, và sau đó toàn bộ điều này trở nên dễ phân tích hơn nhiều.
Charlie Schliesser

Tại sao bạn sẽ kết hợp các mô-đun khác nhau thành một? Ly thân là tốt! (tất nhiên phụ thuộc)
donquixote

Oh tách mối quan tâm là phải! Và các mô-đun có thể vẫn trừu tượng (nghĩa là các mô-đun), nên. Trong dự án cụ thể này, dường như tôi đã có lúc nghĩ rằng mô hình tương tự được áp dụng cho logic kinh doanh đang diễn ra và phát triển trong ứng dụng. Đó thực sự không phải là trường hợp tương tự, và một số mô-đun không thực sự là mô-đun mà là các bộ sưu tập logic PAC không có ý nghĩa nếu không có nhau.
Charlie Schliesser

Tại sao bạn không sử dụng hook_hook_info_alter()thay thế? Các cân nhắc / vấn đề tương tự có được áp dụng nếu tôi sử dụng hook_hook_info_alter()để phân chia các triển khai hook trong một tệp riêng biệt không?
ЕЕннн

hook_hook_info_alter () áp dụng cho tất cả các cài đặt của hook này. Do đó, nó sẽ có tác dụng phụ ngoài ý muốn trên các mô-đun khác.
donquixote 14/03/2016

2

Bất kỳ dự án lớn nào tôi đã làm việc đã chia mọi thứ thành các phần có thể quản lý và dễ dàng chuyển nhượng; về cơ bản kết thúc như @tenken được đề cập ở đây hoặc đến điểm foo.modulecuối cùng chỉ bao gồm:

<?php

module_load_include('inc', 'foo', 'foo.defines');         // bring in our define()s
module_load_include('inc', 'foo', 'foo.HOOK1');           // bring in our HOOK1 functions
module_load_include('inc', 'foo', 'foo.HOOK2');           // bring in our HOOK2 functions

// ...etc

Tất nhiên, tôi cũng đã thấy và sử dụng các tình huống trong đó chỉ có quản trị viên hoặc hiếm khi sử dụng các hook như:

function foo_HOOK(/* $args */) {
  module_load_include('inc', 'foo', 'foo.HOOK');
  return _foo_HOOK(/* $args */);  // _foo_hook() is defined in foo.HOOK.inc
}

vâng, nhìn thấy điều đó và tự làm nó cả hai mặc dù gần đây tôi chỉ thích bao gồm_once __DIR__. '/filename.inc'. Vì vậy, tôi đoán rằng chúng ta đã rõ ràng về câu hỏi 1, nó không phải là không chính thống để phân chia công cụ. Vẫn còn câu hỏi thứ hai, liệu có điều gì xấu có thể xảy ra nếu bạn sử dụng hook_module_implements_alter () cho điều đó. Hoặc lợi ích hiệu suất có thể lớn đến mức nào nếu không bao gồm tệp trên một yêu cầu trung bình, trong đó, ví dụ hook_menu () không được gọi.
donquixote

Btw Cá nhân tôi không thích trò lừa _foo_HOOK () quá nhiều, nó khiến tôi nhìn vào hai nơi thay vì một ..
donquixote

Btw, bạn có thể đơn giản hóa thành module_load_include ('định nghĩa.inc', 'foo'). Nhưng những gì lrfm?
donquixote

lol, lrfm là mô-đun tôi đã cắt và dán nó ra và quên đổi thành foo :)
Jimajamma

đối với việc đơn giản hóa của bạn, vâng, điều đó chắc chắn sẽ có hiệu quả, nhưng đối số đầu tiên được cho là loại tệp và theo các ví dụ trong api.drupal.org/api/drupal/includes%21module.inc/feft/ , Tôi nghi ngờ những gì "sức mạnh drupal tại" được dự định, nhưng chắc chắn ít gõ.
Jimajamma

1

Nếu tôi cố gắng chia nhỏ tệp .module của mình trên nhiều tệp, tôi có xu hướng thực hiện những tính năng cho D7 làm cho các tệp "được bao gồm" của nó mà nó sử dụng bao gồm_once () cho:

include_once('MYMODULE.features.inc');

Đối với D7, tôi vẫn sử dụng "tên không gian chức năng" của mô-đun của mình cho các tệp được bao gồm này và các chức năng mô-đun riêng thường có tiền tố là "_MYMODULE_foo ()".

Câu trả lời này loại bỏ việc bạn muốn sử dụng các lớp Tự động tải và bất kỳ mẫu liên quan đến OO nào bạn đang cố sử dụng trong mã của mình (phụ thuộc mã, v.v.).

Trong vấn đề được liên kết của bạn, có vẻ như bạn muốn sử dụng hook_module_implements_alter () để trở thành một chỉ mục có thể đọc được của những tệp nào có chức năng nào trong tệp .module của bạn. Tôi nghĩ rằng tên tập tin 'MYMODULE.PURPOSE.inc' của sane là đủ để gợi ý cho nhà phát triển việc sử dụng tệp bao gồm trong mô-đun của bạn.


Ý tưởng là chỉ bao gồm các tệp tương ứng khi cần thiết. Tôi đang suy nghĩ về hiệu suất ở đó, nhưng tôi không biết tác động hiệu suất thực tế. Tôi đoán với APC hoặc tương tự, nó không tạo ra sự khác biệt lớn, nhưng tôi không bao giờ đo lường nó.
donquixote

1
@donquixote nếu bạn đang nghĩ về hiệu suất, thì hãy cài đặt APC hoặc bộ đệm opcode khác và đừng bận tâm đến việc chia quá nhiều.
Mołot
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.