0

I intend to programmatically create a widget area for each product category within WooCommerce.

I currently have the following code in my functions.php:

function add_widget_areas() {
    $args = array(
        'taxonomy'   => 'product_cat',
        'hide_empty' => false,
        'parent'     => 0,
    );
    $product_cats = get_terms( $args );

    foreach ( $product_cats as $product_cat ) {
        register_sidebar(
            array(
                'name'          => 'Filter sidebar -' . $product_cat->name,
                'id'            => 'filter_sidebar_' . $product_cat->name,
                'before_widget' => '<div class="filter-sidebar-' . $product_cat->name . '">',
                'after_widget'  => '</div>',
                'before_title'  => '<h2 class="filter-title">',
                'after_title'   => '</h2>',
            )
        );
    }
}
add_action( 'widgets_init', 'add_widget_areas' );

My problem is that this returns an error: Notice: Trying to get property of non-object in .../functions.php on line 752 (line 752: 'name' => 'Filter sidebar -' . $product_cat->name,), presumably because the action for registering widget areas fires before WooCommerce has initialised its product categories.

How do I access the product categories this early in order to make this loop work?

  • 2
    What's in "functions.php on line xyz"? – Max Yudin Mar 1 '18 at 20:01
  • I've edited the question to answer that and improve readability. – Sillzen Mar 2 '18 at 16:11
0

Where is this function hooked?

widgets_init is hooked into init at priority 1, but WooCommerce registers its taxonomies in init at priority 5. So if you use widgets_init as the hook you won't be able to use get_terms() because it returns a WP_Error if the taxonomy isn't registered.

You'll need to register the widget on init at a priority greater than 5 for this to work, and you should still check that the result of get_terms() isn't a WP_Error, in case WooCommerce isn't activated:

function wpse_295558_category_sidebars() {
    $product_cats = get_terms( array(
        'taxonomy'   => 'product_cat',
        'hide_empty' => false,
        'parent'     => 0,
    );

    if ( ! is_wp_error( $product_cats ) ) {
        foreach ( $product_cats as $product_cat ) {
            register_sidebar( array(
                'name'          => 'Filter sidebar -' . $product_cat->name,
                'id'            => 'filter_sidebar_' . $product_cat->name,
                'before_widget' => '<div class="filter-sidebar-' . $product_cat->name . '">',
                'after_widget'  => '</div>',
                'before_title'  => '<h2 class="filter-title">',
                'after_title'   => '</h2>',
            ) );
        }
    }
}
add_action( 'init', 'wpse_295558_category_sidebars', 10 );

This seems like an unwieldy method to achieve whatever you're after though. Wouldn't it be better to have one sidebar for categories and then have the widgets dynamically respond to which category you're viewing? This is already how the bundled filter widgets work in WooCommerce.

  • Thanks for the answer, problem solved! The user needs to be able to add different two different product attribute filters for each category, hence this method. If there is a smarter way to do it, I'd love to know. Cheers! – Sillzen Mar 7 '18 at 12:13
  • As far as I'm aware, the filter widgets will only display if there are relevant products in the current category. So if you put all the widgets in one sidebar, you'll only see the ones relevant to the current category. – Jacob Peattie Mar 7 '18 at 12:16
  • That makes sense, but I don't think that would work in this case due to multiple categories having products with common attributes ('length', 'colour' etc.), where the user would only want one of them to be filterable in that particular category. Thanks for the tip though. – Sillzen Mar 7 '18 at 12:32
0

In general you should not assume anything is set up fully and properly before the init hook (and better to wait for wp_loaded).

Widget registration is happens during the wordpress init process and your code assumes that the taxonomy is already registered before that, which is a very bad assumption to make.

In addition widgets and sidebars need to have a "constant" identifier because it will be used as the key to storing them in the DB, therefor using something that the user can easily change like the category name is not a great idea.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.