Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constructing an instance of TimberPost clears global $product (Woocommerce) #1004

Closed
tomasvanrijsse opened this issue May 17, 2016 · 7 comments
Labels
needs-investigation We've got all the info, now someone needs to look into this to figure out what's going on

Comments

@tomasvanrijsse
Copy link

Expected behavior

We load TimberPost instances from a custom post type with custom fields on the products page.
These instances where loaded first and then the WooCommerce product html was generated.

Actual behavior

Since v1.x of Timber the initialization of an instance of TimberPost will remove the global variable $product.
I've tracked it down to timber/Post.php line 496 where do_action is called for "the_post".
This probably triggers WooCommerce for the second time and WooCommerce probably clears the global $product variable.
Without this variable WooCommerce later on fails and causes a 500 error.

Steps to reproduce behavior

We've made changes to woocommerce/content-single-product.php on the first lines.

 $post = new TimberPost( $post_id );

This will trigger the error if the $post_id references a post with custom fields.

What version of WordPress, PHP and Timber are you using?

WordPress 4.5.2
PHP 5.6.21
Timber 1.0.3

How did you install Timber?

Upgraded to newest version via plugin updater in WordPress dashboard

@connorjburton connorjburton added the needs-investigation We've got all the info, now someone needs to look into this to figure out what's going on label May 17, 2016
@ghost
Copy link

ghost commented Sep 8, 2016

I might've experienced something similar. single-product.php as below works fine unless I call Timber::get_post anywhere else, for example to load additional post data in header.php, after which all of the woo-commerce templates such as sale-flash.php, up-sells.php etc have a $product reference of null, instead of the one we assign below. I got it to work again by moving the get_header() call to the top of single-product.php. I'm not very familiar with the wordpress control flow, what is global scoped, what isn't, and am assuming get_post "pollutes" global scope in some way, but, I'm not sure.

// woocommerce/single-product.php
if (!defined( 'ABSPATH'))
    exit; // Exit if accessed directly

global $post, $product;

$scope = Timber::get_context();
$post = Timber::get_post();
$product = get_product($post->ID);
$scope['post'] = $post;
$scope['product'] = $product;

// move get_header() to the top of our script and single-product.php works again.
get_header('shop');

Timber::render('template/product/single.html', $scope);

get_footer('shop');
// header.php
if (!defined('ABSPATH'))
  exit; // Exit if accessed directly

$scope = Timber::get_context();
// this additional Timber::get_post call is what introduced an issue 
// that was resolved by moving the get_header() call to the top 
// of single-product.php
$scope['nav'] = Timber::get_post([
  'post_type'=> 'page',
  'post_status'=> 'private',
  'pagename'=> 'nav-content',
]);
Timber::render('template/header.html', $scope);

@maciekkus
Copy link

maciekkus commented Dec 13, 2016

Hi, quick and dirty workaround:

add_action( 'the_post', 'wc_setup_product_data_fix',11 );
function wc_setup_product_data_fix() {

    remove_action( 'the_post', 'wc_setup_product_data' );

    return;

}

put it in functions.php
@tomasvanrijsse - thanks for pointing out that the_post action is triggered from timberpost class init method.

@gchtr
Copy link
Member

gchtr commented Apr 30, 2018

This looks very much like #1639.

@Kwapi
Copy link

Kwapi commented Sep 19, 2018

thanks @maciekkus - I've spent the last two days trying to figure out why my Woocommerce setup is not working. It was a barebones Timber theme and a standard Woocommerce integration from here and somehow $product was null.

Here's my stackoverflow question

I'm gonna use @maciekkus 's solution for now and see if anything else breaks. @gchtr - I know you've been working on a solution for this, is there any updates on that?

Cheers

@gchtr
Copy link
Member

gchtr commented Sep 19, 2018

@Kwapi Yes, there are updates. We’ve been working on resolving a lot of issues like the one described here in #1778. That pull request will be the base for improving the WooCommerce Integration that I’m working on. Obviously, the the_post action shouldn’t be called in the constructor of the Timber\Post() class. We’ve moved it in a better place.

I can’t tell you a direct timeframe now, because it’s a little more complex than we first thought and it has implications for other areas in Timber. But I can tell you that WooCommerce is a big priority in this, and you can except that version 2.x of Timber will work really well with WooCommerce without having to use fixes with actions and filters.

In the meantime, to make the product global work, the timber_set_product() function that is described in the Tease Product section of the guide is still the way to go. Or you can try out the integration mentioned above.

@gchtr
Copy link
Member

gchtr commented Oct 9, 2018

I’m going to close this for now, because the changes we made in #1778 also address this issue. It will (hopefully) not occur as soon as Timber 2.x will be released. Feel free to comment on this issue or open a new one. There’s no definite release date for 2.x yet, but we’re working hard on it.

@gchtr gchtr closed this as completed Oct 9, 2018
@kristjankoppel
Copy link

For me this isssue is back with Woocommerce 8.3.1 version. With version 7 everything worked.

global $product just returned NULL.

I also use mindkomm timber-integration-woocommerce version 0.7.1.
Wordpress is at 6.4.1 or 6.4.2 - don't matter same thing.

Current quick fix for me is:

add_action( 'the_post', 'wc_setup_product_data_fix', 11 );
function wc_setup_product_data_fix() {
	if ( is_product() ) {
   		remove_action( 'the_post', 'wc_setup_product_data' );
	}
	return;
}

I added is_product() - otherwise product loops in other places just returned first post object and all posts where the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-investigation We've got all the info, now someone needs to look into this to figure out what's going on
Projects
None yet
Development

No branches or pull requests

6 participants