ฟังก์ชันประมวลผลล่วงหน้าต่อประเภทเนื้อหา


25

ฉันมีเนื้อหาสองสามประเภทซึ่งฉันต้องทำการประมวลผลล่วงหน้าด้วยวิธีที่ต่างกัน ดังนั้นtemplate.phpในธีมของฉันในfooปัจจุบันดูเหมือนว่า:

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) {
    ...
}

ฉันต้องการที่จะสามารถระบุฟังก์ชั่น preprocess เฉพาะ Drupal ซึ่งจะขอเกี่ยวกับชื่อเครื่องของประเภทเนื้อหา ฉันพยายามใช้foo_preprocess_newsแต่มันไม่เคยถูกเรียก

มีวิธีที่ดีกว่า?

คำตอบ:


10

ชื่อของฟังก์ชั่น preprocess จะขึ้นอยู่กับชื่อธีมดังนั้นสำหรับtheme_table()ฟังก์ชั่น preprocess MYTHEME_preprocess_table()ของคุณ

เนื่องจากไม่มีtheme_node_node_typeฟังก์ชั่นเบ็ดประมวลผลล่วงหน้าเช่นfoo_preprocess_newsหรือfoo_preprocess_node_newsจะไม่ทำงานนอกกรอบ

คุณสามารถไปเกี่ยวกับการแทนที่ชุดรูปแบบรีจิสทรีเพื่อให้ทำงานแตกต่างกันไปสำหรับโหนด แต่ฉันไม่อยากจะแนะนำ มันอาจจะยุ่งมาก

ฉันเป็นแฟนตัวยงของรหัส refactoring แต่ในกรณีของคุณฉันไม่คิดว่ามันจำเป็น หากคุณมีตรรกะที่ซับซ้อนที่จำเป็นต้องใช้ในการประมวลผลล่วงหน้าของคุณขึ้นอยู่กับประเภทโหนดแล้วเลี้ยงมันออกไปยังฟังก์ชั่นที่แตกต่างกันในแบบที่คุณทำอยู่ในปัจจุบันดูเหมือนว่าการปฏิบัติที่ดีสำหรับฉัน

แน่นอนว่าวิธีการอื่นจะใช้โมดูลที่กำหนดเองสำหรับเนื้อหาแต่ละประเภทที่แตกต่างกันและนำไปใช้hook_preprocess_node()ในแต่ละรายการ ด้วยวิธีนี้ฟังก์ชั่นการประมวลผลล่วงหน้าของแต่ละโมดูลสามารถรับผิดชอบเนื้อหาที่แตกต่างกันได้

อย่างไรก็ตามสิ่งนี้อาจเกินความจำเป็นสำหรับสถานการณ์ของคุณ หากคุณไม่มีตรรกะเพิ่มเติม (เช่นตรรกะที่ไม่ใช่ชุดรูปแบบการประมวลผลล่วงหน้า) เพื่อดำเนินการกับเนื้อหาแต่ละประเภทวิธีการนี้อาจไม่ได้เพิ่มมูลค่าพิเศษใด ๆ


1
ตกลง. ฉันยังสามารถ "ทำให้เป็นอัตโนมัติ" foo_preprocess_nodeโดยการใช้มันcall_user_func('_preprocess_' . $vars['type'], $vars);เพื่อหลีกเลี่ยงการทำซ้ำ ifs แต่อาจเป็นการดีที่สุดที่จะคงความเรียบง่ายไว้
cherouvim

ฉันใช้งานhook_preprocess_node()ในโมดูลที่กำหนดเองและหวังว่าจะ จำกัด เมื่อมีการเรียกใช้ hook แต่ก็ไม่ได้ วิธีใดที่จะ จำกัด เมื่อมีการเรียกใช้ hook ตามประเภทเนื้อหา
Keven

@Keven คุณไม่สามารถหยุดมันได้ถ้ามีฟังก์ชั่นอยู่ แต่if ($vars['node']->type == 'foo') { ...จะได้เอฟเฟกต์ที่คุณต้องการ
Clive

hook_block_view_MODULE_DELTA_alter()ฉันจริงๆเพียงแค่มองหาการเพิ่มประสิทธิภาพเล็กน้อยคล้ายกับสิ่งที่คุณสามารถทำได้ด้วย ฉันกำลังทำสิ่งที่คุณพูด แต่หวังว่าจะมีวิธี จำกัด เมื่อได้รับความนิยม
Keven

มันจะไม่เป็นการเพิ่มประสิทธิภาพ แต่ @Keven - คุณแค่เปลี่ยนกระบวนการตัดสินใจไปเป็นส่วนอื่นของรหัส ในความเป็นจริงถ้า Drupal เสนอการแทนที่แบบนี้มันจะต้องเป็นแบบทั่วไปและเกือบจะต้องใช้เวลามากขึ้นในการประมวลผล คุณชนะแล้วโดยการตัดสินใจในช่วงเวลาสุดท้าย
ไคลฟ์

28

ธีมย่อย zen ทำสิ่งนี้ได้สำเร็จโดยการเพิ่มสิ่งนี้ไปยังฟังก์ชัน theme_preprocess_node:

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

หากคุณมีประเภทเนื้อหาที่เรียกว่า 'ข่าว' คุณจะสามารถสร้างฟังก์ชั่นที่ชื่อว่า foo_preprocess_node_news ในไฟล์ template.php ของคุณ


นอกจากนี้เรายังใช้สิ่งนี้บนรากฐาน ZURB ด้วยการวางโค้ดขนาดเล็กของเราเองซึ่งมีประโยชน์มาก
Marko Blazekovic

2

ฉันเพิ่งมีปัญหาที่คล้ายกันซึ่งเป็นเหตุผลที่ google นำฉันมาที่หน้านี้: ฟังก์ชั่นการเตรียมประมวลผลโหนดของฉันเติบโตขึ้นอย่างมากขนาดใหญ่ที่ฉันจะแยกฟังก์ชั่นออกเป็นหลายไฟล์

ฉันได้ทำวิธีที่คล้ายกันแล้วในไฟล์ template.php ซึ่งมีฟังก์ชั่นการเปลี่ยนแปลงทั้งหมดและเนื่องจากวิธีการเดียวกันนี้ทำงานได้ดีอย่างสมบูรณ์แบบที่นี่ฉันคิดว่าฉันจะแบ่งปันวิธีการของฉัน:

ตั้งค่าไฟล์ภายในโฟลเดอร์MYTHEME/preprocess:

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

คุณควรมีอยู่แล้วnode.preprocess.incคนอื่น ๆ ที่คุณสามารถสร้างตัวเอง วิธีที่คุณเรียกพวกเขาว่าเป็นเรื่องที่ค่อนข้างไร้เหตุผล แต่ควรให้ชื่อที่ระบุอย่างชัดเจนและเหมาะสมกับระบบการตั้งชื่อ drupal
เป็นต้นไปกับเนื้อหาของไฟล์เหล่านี้!

node.preprocess.incที่นี่ฉันกำลังทำอะไรแบบนี้:

<?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

}

โดยทั่วไปแล้วเราสลับผ่านชนิดของโหนดปัจจุบัน สิ่งที่คุณเปลี่ยนไปนั้นขึ้นอยู่กับคุณ #id, #view_modeทั้งหมดขึ้นอยู่กับความต้องการของคุณ
เมื่อมีการแข่งขันมันจะโหลดไฟล์ที่ระบุและดำเนินการกับเนื้อหาของมันราวกับว่ามันถูกเขียนในฟังก์ชั่นนี้

เนื้อหาของincludedไฟล์เหล่านี้ดูเหมือนว่าคุณจะใส่ไว้ในnode.preprocess.incไฟล์ยกเว้นว่าเราจะไม่เรียกฟังก์ชัน preprocess อีกครั้ง:

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

โดยทั่วไปคุณสามารถทำสิ่งนี้กับไฟล์ได้มากเท่าที่คุณต้องการและแม้แต่เรียงซ้อนสวิตช์หลายตัวตัวอย่างเช่นการแยกไฟล์ preprocess โหนดเฉพาะเพิ่มเติมขึ้นอยู่กับการ#view_modeมีไฟล์หนึ่งไฟล์สำหรับfullโหมดมุมมองและอีกอันสำหรับteaser

หวังว่าสิ่งนี้จะช่วยได้ถ้ามีคนเคยเจอคำถามนี้อีกครั้ง (:


1

call_user_func()ไม่ผ่านพารามิเตอร์โดยการอ้างอิง ดังนั้นในกรณีที่ฟังก์ชั่น$variablesของคุณpreprocess_foo()จะทำงานกับสำเนาของอาร์เรย์เดิมเท่านั้น การเปลี่ยนแปลงที่ไม่ใช่วัตถุจะไม่ใช้ในระหว่างกระบวนการเรนเดอร์ที่เหลือ


1

ใน hook_preprocess_node หลักของคุณใช้รหัสต่อไปนี้ในตอนท้าย

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

ดังนั้นตอนนี้คุณจะมีการประมวลผลล่วงหน้าตามประเภทโหนด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.