Getting Correct Product Link Within WooCommerce Loop When Using Twig And Timber
I have customised some of the WooCommerce templates and I am using the Twig templating system as well as Timber.
On the category pages I have just noticed that the product images all link correctly to the respective products, but the title below them all link to the first product on the page.
The difference between the two is the correct linking section with the photo is customised, and the incorrect linking title is generated via WooCommerce hooks.
Here are my respective files:
archive-product.php
defined( 'ABSPATH' ) || exit;
$context = Timber::get_context();
$context['shop-sidebar'] = Timber::get_widgets( 'shop-sidebar' );
$posts = Timber::get_posts();
$context['products'] = $posts;
$context['search_str'] = (get_search_query()) ? get_search_query() : '';
if ( is_product_category() ) {
$queried_object = get_queried_object();
$term_id = $queried_object->term_id;
$context['category'] = get_term( $term_id, 'product_cat' );
$context['title'] = single_term_title( '', false );
} elseif (is_shop()) {
$shop_id = get_option( 'woocommerce_shop_page_id' );
$post = new TimberPost($shop_id);
$alt_title = (!empty($post->get_field('alt_page_title')['title'])) ? $post->get_field('alt_page_title')['title'] : '';
$context['title'] = ($alt_title) ? $alt_title : $post->post_title;
}
Timber::render( 'views/woo/archive.twig', $context );
views/woo/archive.twig
{% extends 'archive.twig' %} {# Base Archive File #}
{% block before_article %}
{% do action('woocommerce_before_main_content') %}
{% endblock %}
{% block below_h1 %}
{{ fn('woocommerce_result_count') }}
{% endblock %}
{% block intro_content %}
{% do action('woocommerce_archive_description') %}
{% endblock %}
{% block primary_block %}
{% if products|length > 0 %}
<div class="before-products">
{% do action('woocommerce_before_shop_loop') %}
</div>
<div class="products-wrap">
<div class="products row flex">
{% for post in products %}
<div class="product-holder col-xs-6 col-md-4">
{% do action('woocommerce_shop_loop') %}
{% include ["woo/partials/tease-product.twig"] %}
</div>
{% endfor %}
</div>
</div>
{% if fn('show_products_nav') %}
<nav class="pagination" role="navigation">
{{ fn('wp_paginate') }}
</nav>
{% endif %}
<div class="after-products">
{% do action('woocommerce_after_shop_loop') %}
</div>
{% else %}
<div class="no-products">
{% do action('woocommerce_no_products_found') %}
</div>
{% endif %}
{% endblock %}
{% block after_article %}
{% do action('woocommerce_after_main_content') %}
{{ parent() }}
{% endblock %}
woo/partials/tease-product.twig
<article {{ fn('post_class', ['entry'] ) }}>
{{ fn('timber_set_product', post) }}
{% set title = (post.title) ? post.title : fn('the_title') %}
<div class="photo {% if not post.thumbnail %}placeholder{% endif %}">
<a href="{{ post.link }}" class="link">
{% if post.thumbnail %}
<img src="{{ post.thumbnail.src|resize(600)|e('esc_url') }}" class="img-responsive" alt="{{ fn('esc_attr', title) }}" />
{% else %}
<img src="{{ fn('wc_placeholder_img_src') }}" class="img-responsive" alt="Awaiting product image" />
{% endif %}
</a>
</div>
<div class="details">
<h3 class="entry-title">
{% do action('woocommerce_before_shop_loop_item') %}
{% do action('woocommerce_before_shop_loop_item_title') %}
{{ title|e2 }}
{% do action( 'woocommerce_after_shop_loop_item_title' ) %}
{% do action( 'woocommerce_after_shop_loop_item' ) %}
</h3>
</div>
</article>
The problem area is this bit:
<h3 class="entry-title">
{% do action('woocommerce_before_shop_loop_item') %}
{% do action('woocommerce_before_shop_loop_item_title') %}
{{ title|e2 }}
{% do action( 'woocommerce_after_shop_loop_item_title' ) %}
{% do action( 'woocommerce_after_shop_loop_item' ) %}
</h3>
From what I can make out I am able to modify the anchor tag with this:
remove_action( 'woocommerce_before_shop_loop_item', 'woocommerce_template_loop_product_link_open', 10 );
add_action( 'woocommerce_before_shop_loop_item', 'myprefix_woocommerce_template_loop_product_link_open', 10 );
function myprefix_woocommerce_template_loop_product_link_open() {
echo '<a href="https://www.google.com.au/">';
}
I am just not sure where the best place to put this code is and how to pass the correct permalink to it.
Answer
The permalink is accessible via the global product variable, as defined in your partial through {{ fn('timber_set_product', post) }}
Place the code in your functions.php.
remove_action( 'woocommerce_before_shop_loop_item', 'woocommerce_template_loop_product_link_open', 10 );
add_action( 'woocommerce_before_shop_loop_item', 'myprefix_woocommerce_template_loop_product_link_open', 10 );
function myprefix_woocommerce_template_loop_product_link_open() {
global $product;
$link = $product->get_permalink();
echo '<a href="' . esc_url( $link ) . '" class="woocommerce-LoopProduct-link woocommerce-loop-product__link">';
}
Related Questions
- → "failed to open stream" error when executing "migrate:make"
- → October CMS Plugin Routes.php not registering
- → OctoberCMS Migrate Table
- → OctoberCMS Rain User plugin not working or redirecting
- → October CMS Custom Mail Layout
- → October CMS - How to correctly route
- → October CMS create a multi select Form field
- → October CMS - Conditionally Load a Different Page
- → How to disable assets combining on development in OctoberCMS
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → OctoberCms component: How to display all ID(items) instead of sorting only one ID?
- → In OctoberCMS how do you find the hint path?
- → How to register middlewares in OctoberCMS plugin?