iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 24
1
自我挑戰組

Wordpress 外掛開發系列 第 24

「Wordpress 外掛開發」商品與目錄以巢狀顯示

顯示巢狀位置的地方

我們首先先要決定我們的產品列表,及需要改變的頁面,這次舉的範例是我的公司的一些產品列表,而我們先預先設定我們產品的列表:

  • Standard Product(category)
    • standard single flyscreens
    • standard double flyscreens
    • *tilts system(category)
      • standard single tilts
      • standard fireproof tilts
      • standard waterdirve tiles

在一班的顯示頁面下,會先選擇到standard product,進到第二頁則會顯示著兩個single與double這兩項產品,並且還有第二個子目錄,直到點擊進入第二個子目錄,才會把所有商品顯示,而我們的目標是在點入standard product後,以巢狀的方式顯示,並且細載所屬的子項目,來看我們下方的規劃,可以在第二層的目錄就看到更多,而你可能有更複雜的更多的子目錄層層堆疊,我們就不考慮這些使考慮有兩層的使用:

  • Standard product
    • standard single flyscreens
    • standard double flyscreens
  • tilts system
    • standard single tilts
    • standard fireproof tilts
    • standard waterdirve tiles

設定完架構,從哪裡著手

一開始我是朝著回傳的action做開發,但如果你有套主題,你得小心你的archieve-product.php是否有被覆蓋掉,如果沒有的話,我們可以直接朝著對檔案做修改,而如何修改的介紹可以參考這個Template structure & Overriding templates via a theme他的架構時如何組成的,而我們直接改寫woocommerce_locate_template的hook,讓wooCommerce優先執行我們外掛裡頭的模組,改寫後的順序為以下流程:

plugin/template/woocommerce -> theme/yourtheme/woocommerce.php -> theme/yourtheme/woocommerce/ -> 預設模板

此段程式碼節錄於下方網站程式碼,當時看到的時候還不感覺有什麼特別,直到開始寫外掛後才發現extension是一個多麼好用的延伸,而我們就把設定的模板放在plugin/template/woocommerce之中,以便於我們做後續的維護。

add_filter( 'woocommerce_locate_template', 'woo_adon_plugin_template', 1, 3 );
   function woo_adon_plugin_template( $template, $template_name, $template_path ) {
     global $woocommerce;
     $_template = $template;
     if ( ! $template_path ) 
        $template_path = $woocommerce->template_url;
 
     $plugin_path  = untrailingslashit( plugin_dir_path( __FILE__ ) )  . '/template/woocommerce/';
 
    // Look within passed path within the theme - this is priority
    $template = locate_template(
    array(
      $template_path . $template_name,
      $template_name
    )
   );
 
   if( ! $template && file_exists( $plugin_path . $template_name ) )
    $template = $plugin_path . $template_name;
 
   if ( ! $template )
    $template = $_template;

   return $template;
}

content-product_cat.php 顯示子目錄的content的template,大部分在產品之中顯示是否要將所有顯示出來,就會先查到woocommerce_content,而他是把所有項目藉由你的設定給印出來,但不少主題開發者為了省時間是都使用這個來做,而我們今天要使用的,就是將這個content給取代掉,取而代之做出新的loop,而這一段程式碼,主要都是product-archieve.php中的程式碼,而我們在開始之前,我們得先將category的設定更正,設定成defaults,而在customize->woocommerce之中,設定products shop顯示只有product。

https://ithelp.ithome.com.tw/upload/images/20201008/20104531fzLkRry5Kn.jpg

https://ithelp.ithome.com.tw/upload/images/20201008/20104531oe93DtpJoQ.jpg

而我們主要從woocommerce_product_loop_startwoocommerce_product_loop_end改寫新的程式碼,以便於其他目錄可以顯示,而目前我們是針對網址不是product-category而是shop,在母頁面會有一定的影響,而這些調整則是在明天一並做處理,而在加入找post與conditional的邏輯偵測,則是放在woocommerce_before_shop_loop之後。

<?php 
// woocommerce_content();
 if ( is_singular( 'product' ) ) {

    while ( have_posts() ) :
        the_post();
        wc_get_template_part( 'content', 'single-product' );
    endwhile;
		

我們開頭先對於如果是單一產品的品項,做不同的設定,並且直接做輸出,而接下來我們要加入原本的程式碼,而假如我們的subcategory這一些抓取有問題,我們則加入預設的程式碼,而在開頭的前段,我們使用term_id來取得當下的目錄號碼,而可以看到product_categories中有非常多的訊息可以顯示。

if ( woocommerce_product_loop() ) {
      
  do_action( 'woocommerce_before_shop_loop' );
  $term 			= get_queried_object();
  $parent_id 		=  $term->term_id;

  $product_categories = get_categories(
    array(
      'child_of' => $parent_id,
      'taxonomy' => 'product_cat',
      'orderby' => 'name',
      'order' => 'ASC'
    );
  var_dump($product_categories);
  
  if(empty($product_categories)) {

    woocommerce_product_loop_start();
    if ( wc_get_loop_prop( 'total' ) ) {
      while ( have_posts() ) {
        the_post();

        /**
          * Hook: woocommerce_shop_loop.
          *
          * @hooked WC_Structured_Data::generate_product_data() - 10
          */
        do_action( 'woocommerce_shop_loop' );

        wc_get_template_part( 'content', 'product' );
      }
    }
    woocommerce_product_loop_end();
}

而我們下一步,在woocommerce原生之中,wp_query後的have_posts與the_post()來做loop結束的資料,而為何他能夠直接使用have_posts其實我還是不清楚,還沒找到相對的程式碼,而之後我們將開始我們對於product_categories的輸出。

  $product_categories = sort_product($product_categories);
  foreach ($product_categories as $product_category) {
    echo '<h2>'.$product_category->name.'</h2>'.$product_category->term_id;
    woocommerce_product_loop_start(); 
    $args = array(
      'posts_per_page' => -1,
      'post_type' => 'product',
      'tax_query' => array(
        'relation' => 'AND',
        array(
          'taxonomy' => 'product_cat',
          'field' => 'term_id',
          'terms' => $product_category->term_id,
          'include_children' => false
        )
      ),
    );
    $new_cat = new WP_Query( $args );

    while ( $new_cat->have_posts() ) : $new_cat->the_post();
      wc_get_template_part( 'content', 'product' );
    endwhile; 
    wp_reset_postdata();
    woocommerce_product_loop_end(); 
    printf('<div class="content-seperator"></div>');
  }

而我們最後可以看見會使像我下面的介面依樣的結果,而sort_product需要自己撰寫,因為不管是get_categories或是改用wp_get_object_terms,他並不支援以自己的函式做排序處理,而我們的排序又不單純只是照著名字或者數字排序大小,你在這邊可以編輯好你需要的顯示排序,而之後我們進到loop,對每一個目錄做顯示,為了呼應woocommerce的原生寫法,但如果想要自己做喜歡的卡片來擺放,也是可以自己category後的產品中,一個一個抓product title這些來做設定,WP_Query中的參數可以參考get_terms中是如取得的。

最後,完成的畫面就會是巢狀的,明日我們將接續著第二個頁面,將這個顯示到正常的顯示,在product-category中,仍然會有顯示只有subcat的問題,而準備將子目錄加上母目錄的顯示,讓顯示更加完整,明天一並將程式碼改好附上,就可以接著做多重roles的設計!

https://ithelp.ithome.com.tw/upload/images/20201008/20104531ukWF3Mb2X2.jpg

WooCommerce - Nested Category/Subcategory Layout, FIXED: show subcategory content
How to Override WooCommerce Templates in your Plugin
WordPress Plugin Boilerplate
DX Plugin Base
woocommrece content
have_posts


上一篇
「Wordpress 外掛開發」寫完外掛後,然後呢?
下一篇
「Wordpress 外掛開發」商品巢狀表完結篇
系列文
Wordpress 外掛開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言