Hàm tiền xử lý cho mỗi loại nội dung


25

Tôi có một vài loại nội dung mà tôi cần tiền xử lý theo nhiều cách khác nhau. Vì vậy, template.phptrong chủ đề của tôi foohiện tại trông giống như:

function foo_preprocess_node(&$variables) {
    if ('news' ==$variables['type']) _preprocess_news($variables);
    if ('event'==$variables['type']) _preprocess_event($variables);
    if ('alert'==$variables['type']) _preprocess_alert($variables);
    ...
}

function _preprocess_news(&$variables) {
    ...
}

function _preprocess_event(&$variables) {
    ...
}

function _preprocess_alert(&$variables) {
    ...
}

Tôi muốn có thể chỉ định chức năng tiền xử lý cụ thể của Drupal sẽ gắn vào tên máy của loại nội dung. Tôi đã thử sử dụng foo_preprocess_newsnhưng nó không bao giờ được gọi.

Có cách nào tốt hơn?

Câu trả lời:


10

Tên của chức năng tiền xử lý dựa trên tên chủ đề, vì vậy đối với theme_table()chức năng tiền xử lý của bạn là MYTHEME_preprocess_table().

Vì không có theme_node_node_typechức năng, một móc tiền xử lý như foo_preprocess_newshoặc foo_preprocess_node_newssẽ không hoạt động.

Bạn có thể ghi đè lên sổ đăng ký chủ đề để nó hoạt động khác với các nút, nhưng tôi thực sự không khuyến nghị điều đó; nó có thể trở nên rất lộn xộn.

Tôi là một fan hâm mộ lớn của việc tái cấu trúc mã nhưng trong trường hợp của bạn, tôi không nghĩ nó cần thiết; nếu bạn có logic phức tạp cần chạy trong hook pre process của bạn phụ thuộc vào loại nút thì việc đưa nó ra các chức năng khác nhau theo cách bạn đang làm có vẻ như là một cách thực hành tốt đối với tôi.

Tất nhiên, phương pháp khác sẽ là triển khai một mô-đun tùy chỉnh cho từng loại nội dung khác nhau và triển khai hook_preprocess_node()trong mỗi loại. Theo cách đó, chức năng tiền xử lý của mỗi mô-đun có thể chịu trách nhiệm cho một loại nội dung khác nhau.

Tuy nhiên điều này có thể là quá mức cho tình huống của bạn; nếu bạn không có logic bổ sung (tức là logic tiền xử lý không phải chủ đề) để thực hiện trên từng loại nội dung, thì phương pháp này có thể không thêm bất kỳ giá trị bổ sung nào.


1
ĐƯỢC. Tôi cũng có thể "tự động hóa" foo_preprocess_nodebằng cách thực hiện nó như call_user_func('_preprocess_' . $vars['type'], $vars);để tránh lặp lại ifs nhưng tốt nhất là giữ đơn giản.
cherouvim

Tôi đã triển khai hook_preprocess_node()trên một mô-đun tùy chỉnh và hy vọng điều đó sẽ hạn chế khi hook được gọi, nhưng không được. Bất kỳ cách nào để hạn chế khi hook được gọi theo loại nội dung?
Keven

@Keven Bạn không thể ngăn nó được gọi nếu hàm tồn tại, nhưng if ($vars['node']->type == 'foo') { ...sẽ đạt được hiệu quả mà bạn đang tìm kiếm
Clive

Tôi thực sự chỉ đang tìm kiếm tối ưu hóa nhẹ, tương tự như những gì bạn có thể làm với hook_block_view_MODULE_DELTA_alter(). Tôi hiện đang làm những gì bạn nói, nhưng muốn có một cách để hạn chế khi hook bị đánh.
Keven

Nó sẽ không phải là một tối ưu hóa, mặc dù @Keven - bạn sẽ chuyển quá trình ra quyết định sang một phần khác của mã. Trong thực tế nếu Drupal đưa ra một ghi đè như vậy, nó sẽ cần phải chung chung và gần như chắc chắn sẽ mất nhiều thời gian hơn để xử lý. Bạn đã chiến thắng khi chỉ đưa ra quyết định vào phút cuối
Clive

28

Subtheme zen thực hiện điều này bằng cách thêm nó vào hàm theme_pre process_node của nó:

function foo_preprocess_node(&$variables, $hook) {
  ...
    // Optionally, run node-type-specific preprocess functions, like
  // foo_preprocess_node_page() or foo_preprocess_node_story().
  $function = __FUNCTION__ . '_' . $variables['node']->type;
  if (function_exists($function)) {
    $function($variables, $hook);
  } 
  ...
}

Nếu bạn có một loại nội dung gọi là 'news', thì bạn có thể tạo một hàm có tên foo_pre process_node_news trong tệp template.php của bạn.


Chúng tôi cũng sử dụng điều này trên nền tảng ZURB với sự bổ sung của riêng chúng tôi, đoạn mã rất hữu ích.
Marko Blazekovic

2

Tôi chỉ gặp một vấn đề tương tự , đó là lý do tại sao google đưa tôi đến trang này: chức năng tiền xử lý nút của tôi đang phát triển rất lớn, rằng tôi muốn chia chức năng thành nhiều tệp.

Tôi đã thực hiện một cách tiếp cận tương tự trong tệp template.php chứa tất cả các hàm thay đổi và vì cùng một phương thức hoạt động hoàn hảo ở đây, tôi nghĩ tôi muốn chia sẻ cách tiếp cận của mình:

thiết lập tập tin bên trong thư mục MYTHEME/preprocess:

- node.preprocess.inc
- node--blog-post.preprocess.inc
- node--device-variation.preprocess.inc
- (...)

bạn nên có node.preprocess.inc, những người khác bạn có thể tự tạo ra. Làm thế nào bạn gọi chúng thực sự là khá độc đoán, nhưng tốt hơn là đặt cho chúng những cái tên độc đáo xác định chúng và phù hợp với toàn bộ hệ thống đặt tên drupal.
trở đi nội dung của các tập tin này!

node.preprocess.inc, ở đây tôi đang làm một cái gì đó như thế này:

<?php

function MYTHEME_preprocess_node(&$variables) {

    switch($variables['type']) {

      case 'blog_post':
        // if the type of the node is a Blog Post, include this:
        include 'node--blog-post.preprocess.inc';
        break;

      case 'device_variation':
        // if Device Variation, include this:
        include 'node--device-variation.preprocess.inc';
        break;

      case 'foo':
        // ...
        break;
    }

    // additional stuff for all nodes

}

về cơ bản chúng ta chuyển qua loại nút hiện tại. những gì bạn chuyển qua là tùy thuộc vào bạn; #id,, #view_modetất cả tùy thuộc vào nhu cầu chính xác của bạn.
một khi có sự trùng khớp, nó sẽ tải tập tin được chỉ định và hành động theo nội dung của nó giống như nó được viết ngay bên trong hàm này.

nội dung của các includedtệp này trông giống hệt như bạn đặt nó vào node.preprocess.inctệp, ngoại trừ chúng tôi không gọi lại chức năng tiền xử lý:

node--device-variation.preprocess.inc

<?php

    // Device Name
    $device = drupal_clean_css_identifier(strtolower($variables['title']));

    // Determine whether only Device Version is of type 'N/A' and set ppvHasVariations accordingly
    $deviceHasVariations = true;
    if( $variables['content']['product:field_model_variation'][0]['#options']['entity']->weight == 0 ) {
        $deviceHasVariations = false;
    }
    //...

về cơ bản bạn có thể thực hiện việc này với nhiều tệp như bạn muốn và thậm chí xếp tầng nhiều công tắc, ví dụ như chia nhỏ hơn các tệp tiền xử lý nút cụ thể tùy thuộc vào #view_mode, có một tệp cho fullchế độ xem và một tệp khác choteaser

hy vọng điều này có ích, nếu ai đó vấp phải câu hỏi này một lần nữa (:


1

call_user_func()không vượt qua các tham số bằng cách tham chiếu. Vì vậy, trong trường hợp các chức năng $variablescủa bạn preprocess_foo()sẽ chỉ hoạt động trên các bản sao của mảng ban đầu; những thay đổi trên phi đối tượng sẽ không được áp dụng trong quá trình kết xuất còn lại.


1

Trong hook_pre process_node chính của bạn Thực hiện đoạn mã sau ở cuối

$preprocess_function = 'themename_node__' . $node->type . '__preprocess';
if (function_exists($preprocess_function)) {
 $preprocess_function($variables);
}

Vì vậy, bây giờ bạn sẽ có tiền xử lý theo loại nút

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.