woocommerce Theme Flatsome 商品一覧ページの商品一覧をカラム形式とテーブル形式で切り替える

備忘録を残してないと、本当にわからなくなりそうなので。

メインのテンプレート

まず、商品一覧ページは、Woocommerceの設定>「商品」タブ>ショップページ設定 で指定した固定ページが商品一覧ページになる。

商品一覧ページのテンプレート(メインのテンプレート)ファイルは、
/wp-content/themes/flatsome/woocommerce/archive-product.phpである。

商品カテゴリーで抽出した商品一覧(アーカイブ)ページのテンプレートファイルは、

/wp-content/plugins/woocommerce/templates/taxonomy-product-cat.phpである。

しかし、taxonomy-product-cat.php の中身は

wc_get_template( 'archive-product.php' );

なので、結局、商品一覧ページと同じarchive-product.phpである。

カラム形式とテーブル形式を切り替える仕組み

クッキーを使用。表示切替のリンクにjavascriptのonClickイベントで関数を呼び出して、cookieをセットして、ページをリロード。

セットしたクッキーはPHPの$_COOKIEで受取。cookieの値によって、カラム形式とテーブル形式で表示を切り替えるという仕組み。

javascirptのonClickイベント、PHPで$_COOKIEで受取は、archive-product.phpで行うが、ここにはフックがないので、子テーマにarchive-product.phpを作成してカスタマイズをした。

ファイルのパスは、/wp-content/themes/flatsome-child/woocommerce/archive-product.php になる。

archive-product.php では、26行目あたりで

wc_get_template_part( 'layouts/category', flatsome_option( 'category_sidebar' ) );

のように、テンプレートを読み込んでいる。

読み込むテンプレートファイルは、category.phpで、パスは、
/wp-content/themes/flatsome/woocommerce/layouts/category.php なのだが、そのディレクトリにcategory-none.php、category-off-canvas.php、category-right-sidebar.php のファイルがある。
どうやら、wc_get_template_part関数の第2引数によって、読み込むファイルが変わるようだ。

なので、category.phpをカスタマイズをしても、設定が変われば他のテンプレートが読み込まれることになるので、category.phpには手を加えない方法を考える。

出力の切り替え

とりあえず、category.phpの中身を確認。

41行目あたりに、商品一覧のループが始まる。

		<?php

		if ( woocommerce_product_loop() ) {

			/**
			 * Hook: woocommerce_before_shop_loop.
			 *
			 * @hooked wc_print_notices - 10
			 * @hooked woocommerce_result_count - 20 (FL removed)
			 * @hooked woocommerce_catalog_ordering - 30 (FL removed)
			 */
			do_action( 'woocommerce_before_shop_loop' );

			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();

			/**
			 * Hook: woocommerce_after_shop_loop.
			 *
			 * @hooked woocommerce_pagination - 10
			 */
			do_action( 'woocommerce_after_shop_loop' );
		} else {
			/**
			 * Hook: woocommerce_no_products_found.
			 *
			 * @hooked wc_no_products_found - 10
			 */
			do_action( 'woocommerce_no_products_found' );
		}
		?>

上記の

wc_get_template_part( 'content', 'product' );

読み込むテンプレートファイルのパスは、/wp-content/themes/flatsome/woocommerce/content-product.phpで、category-none.php、category-off-canvas.php、category-right-sidebar.phpでも読み込まれるファイルは同じ

なので、content-product.phpで、$_COOKIEの値で条件分岐するようにカスタマイズをする。

カラム形式とテーブル形式の切り替え処理

content-product.phpの中身を確認すると、中身はカラム形式で出力するテンプレート。

このファイルに、カラム形式とテーブル形式の条件分岐を設置して、テーブル形式の出力コードを書くのは、わかりにくかったので、content-product.phpでは、$_COOKIEの値によって、カラム形式のテンプレートを読み込むか、テーブル形式のテンプレートを読み込むかの処理だけにする。

読み込むテンプレートは、カラム形式のテンプレートは、content-product_column.php、テーブル形式のテンプレートは、content-product_table.phpというファイル名で新規に追加。

content-product_column.phpの内容は、wp-content/themes/flatsome/woocommerce/content-product.php のコピペ。

content-product_table.phpには、テーブル形式のHTMLコードを出力するコードを書く。

content-product_column.phpとcontent-product_table.phpは子テーマに配置するので、それぞれのパスは、

/wp-content/themes/flatsome-child/woocommerce/content-product_column.php
/wp-content/themes/flatsome-child/woocommerce/content-product_table.php

content-product.phpも子テーマに配置するので、パスは
/wp-content/themes/flatsome-child/woocommerce/content-product.php

中身は

defined( 'ABSPATH' ) || exit;

$arg = 'product_column' ;
if (array_key_exists('product_loop_layout', $_COOKIE)){
	if($_COOKIE['product_loop_layout'] == "table" && is_archive()){
		$arg = 'product_table';
	}
}

wc_get_template_part( 'content', $arg );

のように、$_COOKIEの値で、読み込むテンプレートをcontent-product_column.phpとcontent-product_table.phpで切り替えている。

条件に is_archive()を入れているのは、商品シングルページに表示される関連商品のループでも表示が変わるから。

content-product_table.phpに表示する商品のデータの配列は、このファイルでgetすることもできるが、content-product_column.phpとcontent-product_table.phpの両方で同じ値を使うので、functions.phpに
my_get_product_data_for_product_archiveという関数を定義して取得するようにしている。

ということで、content-product_table.phpの中身は以下の通り。

defined( 'ABSPATH' ) || exit;

global $product;

// Ensure visibility.
if ( empty( $product ) || false === wc_get_loop_product_visibility( $product->get_id() ) || ! $product->is_visible() ) {
	return;
}
?>
<?php 
$product_data = my_get_product_data_for_product_archive();

?>
<tr>
	<td><span class="product_cat"><a href="<?php echo get_the_permalink(); ?>" target="_blank"><?php echo $product_data['product_cat']['value']?></span><span class="pa_model"><?php echo $product_data['pa_model']['value']?></span></a></td>
	<td class="serial"><a href="<?php echo get_the_permalink(); ?>" target="_blank"><?php echo $product_data['serial']['value']?></a></td>
	<td class="model_year"><a href="<?php echo get_the_permalink(); ?>" target="_blank"><?php echo $product_data['model_year']['value']?></a></td>
	<td class="usage_time"><a href="<?php echo get_the_permalink(); ?>" target="_blank"><?php echo $product_data['usage_time']['value']?></a></td>
	<td class="pa_maker"><a href="<?php echo get_the_permalink(); ?>" target="_blank"><?php echo $product_data['pa_maker']['value']?></a></td>
	<td class="remark"><a href="<?php echo get_the_permalink(); ?>" target="_blank"><?php echo $product_data['remark']['value']?></td>
	<td class="rno"><a href="<?php echo get_the_permalink(); ?>" target="_blank"><?php echo $product_data['rno']['value']?></a></td>
	<td class="enquiry"><?php echo do_shortcode( '[ENQUIRY_BUTTON_DYNAMIC]');?>	</td>
	<td class="price"><a href="<?php echo get_the_permalink(); ?>" target="_blank"><?php echo $product_data['price']['value']?></a></td>
	
</tr>
<?php /* empty PHP to avoid whitespace */ ?>

商品ループ本体の前後のタグの切り替え。

テーブルレイアウトの場合、ループの前には<table>の開始タグとテーブルの見出し行<thead>の出力が必要です。ループ後は</table> (終了タグ)が必要です。

category.phpを見ると、ループの前後に、woocommerce_product_loop_start()とwoocommerce_product_loop_end()がコールされるので、その中身を確認。

この関数は、それぞれ/wp-content/plugins/woocommerce/includes/wc-template-functions.phpに定義されている。

その内容は、それぞれ
/wp-content/themes/flatsome/woocommerce/loop/loop-start.php
/wp-content/themes/flatsome/woocommerce/loop/loop-end.php
を読み込むというもの。

(Flatsomeに当該テンプレートがあるので、上記ディレクトリだが、ない場合は、プラグインディレクトリの wp-content/plugins/woocommerce/templates/loop/loop-start.phpが読み込まれる)

Flatsomeのデフォルトのloop-start.phpとloop-end.phpではdivの開始タグと終了タグを出力して、ループのHTMLを囲んむようになっている。
なので、テーブル形式の時は、デフォルトのdivタグは残したまま、その子要素にtableタグを追加する。loop-start.phpには、テーブルヘッダーも出力する。

出力の条件分岐は、$_COOKIE[‘product_loop_layout’]の値。

//Flatsomeデフォルトのloop-start.php
<?php
/**
 * Product Loop Start
 *
 * @author 		WooThemes
 * @package 	WooCommerce/Templates
 * @version     3.3.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

$cols = esc_attr( wc_get_loop_prop( 'columns' ) );
?>
<div class="products <?php echo flatsome_product_row_classes( $cols ); ?>">
<?php

次がカスタマイズしたloop-start.php 子テーマのディレクトリに配置です。

//カスタマイズしたloop-start.php
<?php
/**
 * Product Loop Start
 *
 * @author 		WooThemes
 * @package 	WooCommerce/Templates
 * @version     3.3.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

$cols = esc_attr( wc_get_loop_prop( 'columns' ) );
?>
<div class="products <?php echo flatsome_product_row_classes( $cols ); ?>">
<?php 
if (array_key_exists('product_loop_layout', $_COOKIE)){
	if( $_COOKIE['product_loop_layout'] == 'table'){?>
		<table class="product_loop_table">
			<tr>
				<th>Category/Model</th>
				<th>Serial</th>
				<th>Model Year</th>
				<th>Usage Time</th>
				<th>Maker</th>
				<th>Remark</th>
				<th>RNO</th>
				<th>Contact</th>
				<th>Price</th>
			</tr>
<?php
	}
}
?>

loop-end.phpもほぼ同様の処理。