I'm trying to show customer last 3 orders on WooCommerce dashboard. But get_template() does not work at all and shows nothing.
I also tried to put orders.php form table in to the dashboard.php template file but It displays no orders here, while already I have some active orders. I'm so confused and have no idea about this problem.
This is my dashboard code:
<?php get_header();?>
<?php
* #see https://docs.woocommerce.com/document/template-structure/
* #package WooCommerce\Templates
* #version 4.4.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
$allowed_html = array(
'a' => array(
'href' => array(),
),
);
?>
<p>
<!-- <?php
printf(
/* translators: 1: user display name 2: logout url */
wp_kses( __( 'Hello %1$s (not %1$s? Log out)', 'woocommerce' ), $allowed_html ),
'<strong>' . esc_html( $current_user->display_name ) . '</strong>',
esc_url( wc_logout_url() )
);
?> -->
</p>
<p>
<?php
/* translators: 1: Orders URL 2: Address URL 3: Account URL. */
// $dashboard_desc = __( 'From your account dashboard you can view your recent orders, manage your billing address, and edit your password and account details.', 'woocommerce' );
// if ( wc_shipping_enabled() ) {
// /* translators: 1: Orders URL 2: Addresses URL 3: Account URL. */
// $dashboard_desc = __( 'From your account dashboard you can view your recent orders, manage your shipping and billing addresses, and edit your password and account details.', 'woocommerce' );
// }
// printf(
// wp_kses( $dashboard_desc, $allowed_html ),
// esc_url( wc_get_endpoint_url( 'orders' ) ),
// esc_url( wc_get_endpoint_url( 'edit-address' ) ),
// esc_url( wc_get_endpoint_url( 'edit-account' ) )
// );
?>
</p>
<?php
/**
* My Account dashboard.
*
* #since 2.6.0
*/?>
<?php do_action( 'woocommerce_account_dashboard' );?>
<div class="row">
<div class="col-10 d-flex dashboard-custom">
<h4>Addresses</h4>
<div class="questionMark">
?
</div>
</div>
<div class="col-2 text-center pt-5 mt-2">
<a href="#" class="viwAdress">
See
</a>
</div>
</div>
<div class="row pt-5">
<div class="adress-dashboard">
<div class="col-12 pt-4 d-flex">
<?php
$fname = get_user_meta( $current_user->ID, 'first_name', true );
$lname = get_user_meta( $current_user->ID, 'last_name', true );
$address_1 = get_user_meta( $current_user->ID, 'billing_address_1', true );
$address_2 = get_user_meta( $current_user->ID, 'billing_address_2', true );
$phonenumber = get_user_meta( $current_user->ID, 'billing_mobile_phone', true );
$city = get_user_meta( $current_user->ID, 'billing_city', true );
$postcode = get_user_meta( $current_user->ID, 'billing_postcode', true );
// echo $fname . "<BR>";
// echo $lname . "<BR>";
// echo $address_1 . "<BR>";
// echo $address_2 . "<BR>";
// echo $city . "<BR>";
// echo $postcode . "<BR>";
?>
<svg id="a47b7a8a-e7bb-4135-b65b-2487268cdcff" width="14" height="17" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 17"><defs><style>.b21eb9b6-977e-44fb-a0e8-fad7fb47a827{fill:#909298;fill-rule:evenodd;}</style></defs><path class="b21eb9b6-977e-44fb-a0e8-fad7fb47a827" d="M10.32,7.26A3.11,3.11,0,1,1,7.21,4.13,3.12,3.12,0,0,1,10.32,7.26Zm-1.55,0A1.56,1.56,0,1,1,7.21,5.7,1.56,1.56,0,0,1,8.77,7.26Z" transform="translate(0 -0.01)"/><path class="b21eb9b6-977e-44fb-a0e8-fad7fb47a827" d="M2.17,12.15a7.07,7.07,0,0,1-.24-10A7,7,0,0,1,11.83,2a7.07,7.07,0,0,1,.24,10L7.24,17Zm8.77-1.32-3.75,4L3.25,11a5.5,5.5,0,0,1-.19-7.75,5.42,5.42,0,0,1,7.69-.19A5.5,5.5,0,0,1,10.94,10.83Z" transform="translate(0 -0.01)"/>
</svg>
<h5><?php echo $address_1; ?></h5>
</div>
<div class="col-12 d-flex pt-4">
<svg id="bd6f5e62-b10a-4e71-b77c-d5f9368c28e6" width="14" height="17" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11 18"><defs><style>.a30aed3e-ff50-49ef-a803-e1cfe573925c,.fa1d0d58-d038-41f3-bd11-17bb673b76c2{fill:#909298;}.a30aed3e-ff50-49ef-a803-e1cfe573925c{fill-rule:evenodd;}</style></defs><path class="a30aed3e-ff50-49ef-a803-e1cfe573925c" d="M9.17,4A3.84,3.84,0,0,1,5.5,8,3.84,3.84,0,0,1,1.83,4,3.84,3.84,0,0,1,5.5,0,3.84,3.84,0,0,1,9.17,4ZM7.33,4A1.92,1.92,0,0,1,5.5,6,1.92,1.92,0,0,1,3.67,4,1.92,1.92,0,0,1,5.5,2,1.92,1.92,0,0,1,7.33,4Z"/><path class="fa1d0d58-d038-41f3-bd11-17bb673b76c2" d="M9.17,12a1,1,0,0,0-.92-1H2.75a1,1,0,0,0-.92,1v6H0V12A2.88,2.88,0,0,1,2.75,9h5.5A2.88,2.88,0,0,1,11,12v6H9.17Z"/>
</svg>
<h5>Customer :<?php echo $fname ; ?> </h5>
</div>
<div class="col-12 d-flex pt-4">
<h5>Phone :<?php echo $phonenumber; ?> </h5>
</div>
<div class="col-12 d-flex pt-4">
<h5>ZipCode:<?php echo $postcode ; ?> </h5>
</div>
</div>
<!-- adres box -->
</div>
<?php
/**
* Deprecated woocommerce_before_my_account action.
*
* #deprecated 2.6.0
*/
do_action( 'woocommerce_before_my_account' );
/**
* Deprecated woocommerce_after_my_account action.
*
* #deprecated 2.6.0
*/
do_action( 'woocommerce_after_my_account' );
/* Omit closing PHP tag at the end of PHP files to avoid "headers already sent" issues. */?>
</section>
And this is my Order template code that work on Orders Tab but don't work on dashboard Tab:
<?php
/**
* My Orders - Deprecated
*
* #deprecated 2.6.0 this template file is no longer used. My Account shortcode uses orders.php.
* #package WooCommerce\Templates
*/
defined('ABSPATH') || exit;
$my_orders_columns = apply_filters(
'woocommerce_my_account_my_orders_columns',
array(
'order-number' => esc_html__('Order', 'woocommerce'),
'order-date' => esc_html__('Date', 'woocommerce'),
'order-status' => esc_html__('Status', 'woocommerce'),
'order-total' => esc_html__('Total', 'woocommerce'),
'order-actions' => ' ',
)
);
$customer_orders = get_posts(
apply_filters(
'woocommerce_my_account_my_orders_query',
array(
'numberposts' => $order_count,
'meta_key' => '_customer_user',
'meta_value' => get_current_user_id(),
'post_type' => wc_get_order_types('view-orders'),
'post_status' => array_keys(wc_get_order_statuses()),
)
)
); ?>
<?php if ($customer_orders) : ?>
<h2><?php echo apply_filters('woocommerce_my_account_my_orders_title', esc_html__('Recent orders', 'woocommerce')); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></h2>
<table class="shop_table shop_table_responsive my_account_orders">
<thead>
<tr>
<?php foreach ($my_orders_columns as $column_id => $column_name) : ?>
<th class="<?php echo esc_attr($column_id); ?>"><span
class="nobr"><?php echo esc_html($column_name); ?></span></th>
<?php endforeach; ?>
</tr>
</thead>
<tbody>
<?php
foreach ($customer_orders as $customer_order) :
$order = wc_get_order($customer_order); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$item_count = $order->get_item_count();
?>
<tr class="order">
<?php foreach ($my_orders_columns as $column_id => $column_name) : ?>
<td class="<?php echo esc_attr($column_id); ?>" data-title="<?php echo esc_attr($column_name); ?>">
<?php if (has_action('woocommerce_my_account_my_orders_column_' . $column_id)) : ?>
<?php do_action('woocommerce_my_account_my_orders_column_' . $column_id, $order); ?>
<?php elseif ('order-number' === $column_id) : ?>
<a href="<?php echo esc_url($order->get_view_order_url()); ?>">
<?php echo _x('#', 'hash before order number', 'woocommerce') . $order->get_order_number(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</a>
<?php elseif ('order-date' === $column_id) : ?>
<time datetime="<?php echo esc_attr($order->get_date_created()->date('c')); ?>"><?php echo esc_html(wc_format_datetime($order->get_date_created())); ?></time>
<?php elseif ('order-status' === $column_id) : ?>
<?php echo esc_html(wc_get_order_status_name($order->get_status())); ?>
<?php elseif ('order-total' === $column_id) : ?>
<?php
/* translators: 1: formatted order total 2: total order items */
printf(_n('%1$s for %2$s item', '%1$s for %2$s items', $item_count, 'woocommerce'), $order->get_formatted_order_total(), $item_count); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
<?php elseif ('order-actions' === $column_id) : ?>
<?php
$actions = wc_get_account_orders_actions($order);
if (!empty($actions)) {
foreach ($actions as $key => $action) { // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
echo '' . esc_html($action['name']) . '';
}
}
?>
<?php endif; ?>
</td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<?php
wc_get_template( 'myaccount/orders.php' );
?>
No need to overwrite template files, you can use the woocommerce_account_dashboard hook
Most of the code was copied from myaccount/orders.php template file,
here and there, however, there is an adjustment so that directly copying the template file is not a (complete) solution.
So you get:
function action_woocommerce_account_dashboard() {
// Set limit
$limit = 3;
// Get customer $limit last orders
$customer_orders = wc_get_orders( array(
'customer' => get_current_user_id(),
'limit' => $limit
) );
// Count customers orders
$count = count( $customer_orders );
// Greater than or equal to
if ( $count >= 1 ) {
// Message
echo '<p>' . sprintf( _n( 'Your last order', 'Your last %s orders', $count, 'woocommerce' ), $count ) . '</p>';
?>
<table class="woocommerce-orders-table woocommerce-MyAccount-orders shop_table shop_table_responsive my_account_orders account-orders-table">
<thead>
<tr>
<?php foreach ( wc_get_account_orders_columns() as $column_id => $column_name ) : ?>
<th class="woocommerce-orders-table__header woocommerce-orders-table__header-<?php echo esc_attr( $column_id ); ?>"><span class="nobr"><?php echo esc_html( $column_name ); ?></span></th>
<?php endforeach; ?>
</tr>
</thead>
<tbody>
<?php
foreach ( $customer_orders as $customer_order ) {
$order = wc_get_order( $customer_order ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$item_count = $order->get_item_count() - $order->get_item_count_refunded();
?>
<tr class="woocommerce-orders-table__row woocommerce-orders-table__row--status-<?php echo esc_attr( $order->get_status() ); ?> order">
<?php foreach ( wc_get_account_orders_columns() as $column_id => $column_name ) : ?>
<td class="woocommerce-orders-table__cell woocommerce-orders-table__cell-<?php echo esc_attr( $column_id ); ?>" data-title="<?php echo esc_attr( $column_name ); ?>">
<?php if ( has_action( 'woocommerce_my_account_my_orders_column_' . $column_id ) ) : ?>
<?php do_action( 'woocommerce_my_account_my_orders_column_' . $column_id, $order ); ?>
<?php elseif ( 'order-number' === $column_id ) : ?>
<a href="<?php echo esc_url( $order->get_view_order_url() ); ?>">
<?php echo esc_html( _x( '#', 'hash before order number', 'woocommerce' ) . $order->get_order_number() ); ?>
</a>
<?php elseif ( 'order-date' === $column_id ) : ?>
<time datetime="<?php echo esc_attr( $order->get_date_created()->date( 'c' ) ); ?>"><?php echo esc_html( wc_format_datetime( $order->get_date_created() ) ); ?></time>
<?php elseif ( 'order-status' === $column_id ) : ?>
<?php echo esc_html( wc_get_order_status_name( $order->get_status() ) ); ?>
<?php elseif ( 'order-total' === $column_id ) : ?>
<?php
/* translators: 1: formatted order total 2: total order items */
echo wp_kses_post( sprintf( _n( '%1$s for %2$s item', '%1$s for %2$s items', $item_count, 'woocommerce' ), $order->get_formatted_order_total(), $item_count ) );
?>
<?php elseif ( 'order-actions' === $column_id ) : ?>
<?php
$actions = wc_get_account_orders_actions( $order );
if ( ! empty( $actions ) ) {
foreach ( $actions as $key => $action ) { // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
echo '' . esc_html( $action['name'] ) . '';
}
}
?>
<?php endif; ?>
</td>
<?php endforeach; ?>
</tr>
<?php
}
?>
</tbody>
</table>
<?php
} else {
?>
<div class="woocommerce-message woocommerce-message--info woocommerce-Message woocommerce-Message--info woocommerce-info">
<a class="woocommerce-Button button" href="<?php echo esc_url( apply_filters( 'woocommerce_return_to_shop_redirect', wc_get_page_permalink( 'shop' ) ) ); ?>"><?php esc_html_e( 'Browse products', 'woocommerce' ); ?></a>
<?php esc_html_e( 'No order has been made yet.', 'woocommerce' ); ?>
</div>
<?php
}
}
add_action( 'woocommerce_account_dashboard', 'action_woocommerce_account_dashboard' );
Code goes in functions.php file of the active child theme (or active theme).
I added a custom download link for my resellers to download product images. But I would like to add target="_blank" rel="noopener noreferrer" attributes to the link.
Here's my custom download link:
// Add a Custom Download File to My Account
add_filter( 'woocommerce_customer_get_downloadable_products', 'my_custom_default_download', 9999, 1 );
function my_custom_default_download( $downloads ) {
if ( is_admin() && !defined('DOING_AJAX') )
return;
// Only on checkout page and logged in users
if ( ! is_wc_endpoint_url() || ! is_user_logged_in() )
return;
$wpuser_object = wp_get_current_user();
$allowed_roles = array( 'administrator', 'default_wholesaler', 'wholesaler-non-vat-registered', 'wholesaler-ex-vat-registered', 'wholesaler-ex-non-vat-registered', 'shop_manager');
if ( array_intersect($allowed_roles, $wpuser_object->roles) ){
$downloads[] = array(
'product_name' => 'Product Images (High Resolution)',
'download_name' => 'Download',
'download_url' => 'https://drive.google.com/drive/folders/',
);
return $downloads;
}
}
Here's the updated my-downloads.php file saved to my child theme:
<?php
defined( 'ABSPATH' ) || exit;
$downloads = WC()->customer->get_downloadable_products();
if ( $downloads ) : ?>
<?php do_action( 'woocommerce_before_available_downloads' ); ?>
<h2><?php echo apply_filters( 'woocommerce_my_account_my_downloads_title', esc_html__( 'Available downloads', 'woocommerce' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></h2>
<ul class="woocommerce-Downloads digital-downloads">
<?php foreach ( $downloads as $download ) : ?>
<li>
<?php
do_action( 'woocommerce_available_download_start', $download );
if ( is_numeric( $download['downloads_remaining'] ) ) {
/* translators: %s product name */
echo apply_filters( 'woocommerce_available_download_count', '<span class="woocommerce-Count count">' . sprintf( _n( '%s download remaining', '%s downloads remaining', $download['downloads_remaining'], 'woocommerce' ), $download['downloads_remaining'] ) . '</span> ', $download ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo apply_filters( 'woocommerce_available_download_link', '' . $download['download_name'] . '', $download ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
do_action( 'woocommerce_available_download_end', $download );
?>
</li>
<?php endforeach; ?>
</ul>
<?php do_action( 'woocommerce_after_available_downloads' ); ?>
<?php endif; ?>
You've got to update the order-downloads.php file not the my-downloads.php file and save it to the child theme.
Here's the solution:
<?php
/**
* Order Downloads.
*
* This template can be overridden by copying it to yourtheme/woocommerce/order/order-downloads.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* #see https://docs.woocommerce.com/document/template-structure/
* #package WooCommerce\Templates
* #version 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<section class="woocommerce-order-downloads">
<?php if ( isset( $show_title ) ) : ?>
<h2 class="woocommerce-order-downloads__title"><?php esc_html_e( 'Downloads', 'woocommerce' ); ?></h2>
<?php endif; ?>
<table class="woocommerce-table woocommerce-table--order-downloads shop_table shop_table_responsive order_details">
<thead>
<tr>
<?php foreach ( wc_get_account_downloads_columns() as $column_id => $column_name ) : ?>
<th class="<?php echo esc_attr( $column_id ); ?>"><span class="nobr"><?php echo esc_html( $column_name ); ?></span></th>
<?php endforeach; ?>
</tr>
</thead>
<?php foreach ( $downloads as $download ) : ?>
<tr>
<?php foreach ( wc_get_account_downloads_columns() as $column_id => $column_name ) : ?>
<td class="<?php echo esc_attr( $column_id ); ?>" data-title="<?php echo esc_attr( $column_name ); ?>">
<?php
if ( has_action( 'woocommerce_account_downloads_column_' . $column_id ) ) {
do_action( 'woocommerce_account_downloads_column_' . $column_id, $download );
} else {
switch ( $column_id ) {
case 'download-product':
if ( $download['product_url'] ) {
echo '' . esc_html( $download['product_name'] ) . '';
} else {
echo esc_html( $download['product_name'] );
}
break;
case 'download-file':
echo '' . esc_html( $download['download_name'] ) . '';
break;
case 'download-remaining':
echo is_numeric( $download['downloads_remaining'] ) ? esc_html( $download['downloads_remaining'] ) : esc_html__( '∞', 'woocommerce' );
break;
case 'download-expires':
if ( ! empty( $download['access_expires'] ) ) {
echo '<time datetime="' . esc_attr( date( 'Y-m-d', strtotime( $download['access_expires'] ) ) ) . '" title="' . esc_attr( strtotime( $download['access_expires'] ) ) . '">' . esc_html( date_i18n( get_option( 'date_format' ), strtotime( $download['access_expires'] ) ) ) . '</time>';
} else {
esc_html_e( 'Never', 'woocommerce' );
}
break;
}
}
?>
</td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</table>
</section>
In WooCommerce, I'm trying to add some custom code into my active theme's functions.php file, which will enable for variable products to display the attribute dropdowns, the quantity field and the add to cart button on shop and archive pages.
Here's my actual code:
// Display variations dropdowns on shop page for variable products
add_filter( 'woocommerce_loop_add_to_cart_link', 'woo_display_variation_dropdown_on_shop_page' );
function woo_display_variation_dropdown_on_shop_page() {
global $product;
if( $product->is_type( 'variable' )) {
$attribute_keys = array_keys( $product->get_attributes() );
?>
<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->id ); ?>" data-product_variations="<?php echo htmlspecialchars( json_encode( $product->get_available_variations() ) ) ?>">
<?php do_action( 'woocommerce_before_variations_form' ); ?>
<?php if ( empty( $product->get_available_variations() ) && false !== $product->get_available_variations() ) : ?>
<p class="stock out-of-stock"><?php _e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></p>
<?php else : ?>
<table class="variations" cellspacing="0">
<tbody>
<?php foreach ( $product->get_attributes() as $attribute_name => $options ) : ?>
<tr>
<td class="label"><label for="<?php echo sanitize_title( $attribute_name ); ?>"><?php echo wc_attribute_label( $attribute_name ); ?></label></td>
<td class="value">
<?php
$selected = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( urldecode( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ) : $product->get_variation_default_attribute( $attribute_name );
wc_dropdown_variation_attribute_options( array( 'options' => $options, 'attribute' => $attribute_name, 'product' => $product, 'selected' => $selected ) );
echo end( $attribute_keys ) === $attribute_name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<?php do_action( 'woocommerce_before_add_to_cart_button' ); ?>
<div class="single_variation_wrap">
<?php
/**
* woocommerce_before_single_variation Hook.
*/
do_action( 'woocommerce_before_single_variation' );
/**
* woocommerce_single_variation hook. Used to output the cart button and placeholder for variation data.
* #since 2.4.0
* #hooked woocommerce_single_variation - 10 Empty div for variation data.
* #hooked woocommerce_single_variation_add_to_cart_button - 20 Qty and cart button.
*/
do_action( 'woocommerce_single_variation' );
/**
* woocommerce_after_single_variation Hook.
*/
do_action( 'woocommerce_after_single_variation' );
?>
</div>
<?php do_action( 'woocommerce_after_add_to_cart_button' ); ?>
<?php endif; ?>
<?php do_action( 'woocommerce_after_variations_form' ); ?>
</form>
<?php } else {
echo sprintf( '<a rel="nofollow" href="%s" data-quantity="%s" data-product_id="%s" data-product_sku="%s" class="%s">%s</a>',
esc_url( $product->add_to_cart_url() ),
esc_attr( isset( $quantity ) ? $quantity : 1 ),
esc_attr( $product->id ),
esc_attr( $product->get_sku() ),
esc_attr( isset( $class ) ? $class : 'button' ),
esc_html( $product->add_to_cart_text() )
);
}
}
But the following errors are thrown and having issues making it work:
Your PHP code changes were rolled back due to an error on line 666 of file wp-content/plugins/woocommerce-composite-products/includes/wc-cp-template-functions.php. Please fix and try saving again.
Uncaught Error: Call to a member function get_type() on null in
wp-content/plugins/woocommerce-composite-products/includes/wc-cp-template-functions.php:666
Stack trace:
#0 wp-includes/class-wp-hook.php(286): wc_cp_before_add_to_cart_button('')
#1 wp-includes/class-wp-hook.php(310): WP_Hook->apply_filters('', Array)
#2 wp-includes/plugin.php(465): WP_Hook->do_action(Array)
#3 wp-content/themes/electro-child/functions.php(2228): do_action('woocommerce_bef...')
#4 wp-includes/class-wp-hook.php(288): woo_display_variation_dropdown_on_shop_page('<a href="https:...')
#5 wp-includes/plugin.php(208): WP_Hook->apply_filters('<a href="https:...', Array)
#6 wp-content/plugins/woocommerce/templates/loop/add
I think there's a conflict with the Composite product plugin I'm using.
Any help is hugely appreciated.
The biggest mistake in your code is that you just forgot that you are using a filter hook and in that case, you need to return the output, but not to echo it.
Then you will use the hook arguments that are included in this filter hook instead.
Also you just need to change the behavior for variable products only, because, with your actual code, as you are also using the WooCommerce Composite Products plugin, it gives you the reported error.
So try instead something like (untested):
// Display variations dropdowns on shop page for variable products
add_filter( 'woocommerce_loop_add_to_cart_link', 'woo_display_variation_dropdown_on_shop_page', 10, 3 );
function woo_display_variation_dropdown_on_shop_page( $add_to_cart_link, $product, $args ) {
if( $product->is_type('variable') ) {
$attribute_keys = array_keys( $product->get_attributes() );
ob_start(); // Start buffering
?>
<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->id ); ?>" data-product_variations="<?php echo htmlspecialchars( json_encode( $product->get_available_variations() ) ) ?>">
<?php do_action( 'woocommerce_before_variations_form' ); ?>
<?php if ( empty( $product->get_available_variations() ) && false !== $product->get_available_variations() ) : ?>
<p class="stock out-of-stock"><?php _e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></p>
<?php else : ?>
<table class="variations" cellspacing="0">
<tbody>
<?php foreach ( $product->get_attributes() as $attribute_name => $options ) : ?>
<tr>
<td class="label"><label for="<?php echo sanitize_title( $attribute_name ); ?>"><?php echo wc_attribute_label( $attribute_name ); ?></label></td>
<td class="value">
<?php
$selected = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( urldecode( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ) : $product->get_variation_default_attribute( $attribute_name );
wc_dropdown_variation_attribute_options( array( 'options' => $options, 'attribute' => $attribute_name, 'product' => $product, 'selected' => $selected ) );
echo end( $attribute_keys ) === $attribute_name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<?php do_action( 'woocommerce_before_add_to_cart_button' ); ?>
<div class="single_variation_wrap">
<?php
/**
* woocommerce_before_single_variation Hook.
*/
do_action( 'woocommerce_before_single_variation' );
/**
* woocommerce_single_variation hook. Used to output the cart button and placeholder for variation data.
* #since 2.4.0
* #hooked woocommerce_single_variation - 10 Empty div for variation data.
* #hooked woocommerce_single_variation_add_to_cart_button - 20 Qty and cart button.
*/
do_action( 'woocommerce_single_variation' );
/**
* woocommerce_after_single_variation Hook.
*/
do_action( 'woocommerce_after_single_variation' );
?>
</div>
<?php do_action( 'woocommerce_after_add_to_cart_button' ); ?>
<?php endif; ?>
<?php do_action( 'woocommerce_after_variations_form' ); ?>
</form>
<?php
$add_to_cart_link = ob_get_clean(); // The buffered content
}
return $add_to_cart_link;
}
Having trouble implementing the pagination for custom post type ('vehicle') in Genesis child theme, I'm using Genesis : 2.0.0 in wordpress 4.1.1
I've tried placing the following code in function.php
add_filter( 'genesis_prev_link_text', 'gt_review_prev_link_text' );
function gt_review_prev_link_text() {
$prevlink = '« Previous Reviews';
return $prevlink;
}
add_filter( 'genesis_next_link_text', 'gt_review_next_link_text' );
function gt_review_next_link_text() {
$nextlink = 'Next Reviews »';
return $nextlink;
}
i've tried the following too;
<?php genesis_posts_nav();?>
The code below works, but only as 'newer' and 'older' hyperlinks, i'm trying to achieve a numeric pagination.
<?php previous_posts_link( '« Newer' ); ?>
<?php next_posts_link( 'Older »', $vehicle->max_num_pages ); ?>
Here is my custom post type archive template.
<?php
/*
Template Name: Archive Vehicle(CAR)
*/
//* Force full width content
add_filter( 'genesis_pre_get_option_site_layout', '__genesis_return_full_width_content' );
//* Remove Post Info
remove_action( 'genesis_entry_header', 'genesis_post_info', 12 );
//* Remove Post Meta
remove_action( 'genesis_entry_footer', 'genesis_entry_footer_markup_open', 5 );
remove_action( 'genesis_entry_footer', 'genesis_entry_footer_markup_close', 15 );
remove_action( 'genesis_entry_footer', 'genesis_post_meta' );
/** Code for custom loop */
remove_action( 'genesis_loop', 'genesis_do_loop' );
add_action( 'genesis_loop', 'am_custom_loop' );
function am_custom_loop(){
$paged = 1;
if ( get_query_var( 'paged' ) ) { $paged = get_query_var( 'paged' ); }
if ( get_query_var( 'page' ) ) { $paged = get_query_var( 'page' ); }
$paged = intval( $paged );
$args = array('post_type' => 'vehicle', 'posts_per_page' => '3', 'paged'=> $paged, );
$vehicle = new WP_query($args);
$wp_query = $vehicle;
if ($vehicle -> have_posts() ){
?>
<div class="first arc">
<h2> View our latest used car collection from KH cars Birmingham</h2>
<p>Need a car? Look no further, browse through our vast selection of used cars on site based in Birmingham. </p>
</div>
<?php
while ($vehicle -> have_posts() ){
$vehicle -> the_post();
?>
<div class="first archivecar">
<div class="one-fourth">
<?php
$images = get_field('image');
if( $images ):
$image = $images[0];
?>
<a href="<?php the_permalink($id); ?>">
<img src="<?php echo $images[0]['sizes']['large']; ?>" alt="<?php echo $image['alt']; ?>" />
</a>
<?php endif; ?>
</div>
<div class="two-fourths">
<br>
<h3><a style="text-decoration:none;" href="<?php the_permalink($id) ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h3>
<ul class="carinfo">
<li><p> Year: <?php $terms = get_the_terms( $post->ID , 'year', 'year' );
// Loop over each item since it's an array
if ( $terms != null ){
foreach( $terms as $term ) {
// Print the name method from $term which is an OBJECT
print $term->name ;
// Get rid of the other data stored in the object, since it's not needed
unset($term);
} } ?></p></li>
<li><p> Trans: <?php $terms = get_the_terms( $post->ID , 'trans', 'trans' );
// Loop over each item since it's an array
if ( $terms != null ){
foreach( $terms as $term ) {
// Print the name method from $term which is an OBJECT
print $term->name ;
// Get rid of the other data stored in the object, since it's not needed
unset($term);
} } ?></p></li>
<li><p> Fuel:
<?php // Get terms for post
$terms = get_the_terms( $post->ID , 'fuel', 'fuel' );
// Loop over each item since it's an array
if ( $terms != null ){
foreach( $terms as $term ) {
// Print the name method from $term which is an OBJECT
print $term->name ;
// Get rid of the other data stored in the object, since it's not needed
unset($term);
} } ?></li>
<?php if( get_field('Mileage') ): ?>
<li><p> Mileage: <?php the_field('Mileage');?></p></li>
<?php endif; ?>
<li><p>Color: <?php $terms = get_the_terms( $post->ID , 'colours', 'colours' );
// Loop over each item since it's an array
if ( $terms != null ){
foreach( $terms as $term ) {
// Print the name method from $term which is an OBJECT
print $term->name ;
// Get rid of the other data stored in the object, since it's not needed
unset($term);
} } ?></p></li>
<?php if( get_field('owners') ): ?>
<li><p>Owners: <?php $terms = get_the_terms( $post->ID , 'owners', 'owners' );
// Loop over each item since it's an array
if ( $terms != null ){
foreach( $terms as $term ) {
// Print the name method from $term which is an OBJECT
print $term->name ;
// Get rid of the other data stored in the object, since it's not needed
unset($term);
} }?></p></li>
<?php endif; ?>
</ul>
</div>
<div class="one-fourth">
<?php if ( get_field('price')):?>
<p class="price"><?php the_field('price');?></p>
<?php endif; ?>
<a class="btn" style="text-align:center" href="<?php the_permalink() ?>">view Details</a>
</div>
</div>
<?php
}
?>
<?php genesis_posts_nav();?>
<?php wp_reset_query();?>
<?php
}
}
genesis();
Any Help is much appreciated. Thanks in advance
First i Removed $wp_query = $vehicle; and then used the code below from wordpress codex and voila it works.
<?php
$big = 999999999; // need an unlikely integer
echo paginate_links( array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var('paged') ),
'total' => $vehicle->max_num_pages
) );
?>
Here's what I'm attempting to do and where.
In the check out process for an order, in the plug-in WooCommerce; you are taken to a page when the check out is process is complete. It displays an overview of the order details. The template file used to output this page is order-details.php.
Here's what I'd like to add
I would like to display the product's product category like so:
This is area of code I'm attempting to add to, the first section of the order details table.
<tbody>
<?php
if ( sizeof( $order->get_items() ) > 0 ) {
foreach( $order->get_items() as $item ) {
$_product = apply_filters( 'woocommerce_order_item_product', $order->get_product_from_item( $item ), $item );
$item_meta = new WC_Order_Item_Meta( $item['item_meta'], $_product );
?>
<tr class="<?php echo esc_attr( apply_filters( 'woocommerce_order_item_class', 'order_item', $item, $order ) ); ?>">
<td class="product-name">
<?php
if ( $_product && ! $_product->is_visible() )
echo apply_filters( 'woocommerce_order_item_name', $item['name'], $item );
else
echo apply_filters( 'woocommerce_order_item_name', sprintf( '%s', get_permalink( $item['product_id'] ), $item['name'] ), $item );
echo apply_filters( 'woocommerce_order_item_quantity_html', ' <strong class="product-quantity">' . sprintf( '× %s', $item['qty'] ) . '</strong>', $item );
This is my understanding so far;
That a custom query is being applied.
That for each product listed details are being echoed.
That a WooCommerce Class is being used to get specific product meta.
My understandings are observations at my current knowledge level.
What I was hoping was that I could use something like
echo apply_filters( 'woocommerce_order_item_name', ' <strong class="product-category">' . e_( $item['product_cat'] ) . '</strong>', $item );
I can't find a more relevant filter and I'm really not sure that ['product_cat'] is even relevant here. This is an example of the way I'm attempting to solve my requirement.
As you can tell, I don't work in PHP full time. I'm learning as much as I can when I can. Advise would be greatly appreciated
This is how you might add the product categories to the Product title. I don't particularly like how it is outputting for me, but then I am testing it on a variable subscription, so that is amending its own data. This would go in your theme's functions.php
function kia_woocommerce_order_item_name( $name, $item ){
$product_id = $item['product_id'];
$tax = 'product_cat';
$terms = wp_get_post_terms( $product_id, $tax, array( 'fields' => 'names' ) );
if( $terms && ! is_wp_error( $terms )) {
$taxonomy = get_taxonomy($tax);
$name .= '<label>' . $taxonomy->label . ': </label>' . implode( ', ', $terms );
}
return $name;
}
add_filter( 'woocommerce_order_item_name', 'kia_woocommerce_order_item_name', 10, 2 );
Otherwise you could copy the order-details.php template into your own theme (so yourtheme/woocommerce/order/order-details.php and add the code directly. This would give you more control over where you want the category to appear since there aren't a lot of hooks available in this section, but put you at risk if WooCommerce ever modifies this code. I have worked on a few sites that broke because the the theme was using outdated template.
Any way, an example would be:
<?php
/**
* Order details
*
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.2.0
*/
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
global $woocommerce;
$order = new WC_Order( $order_id );
?>
<h2><?php _e( 'Order Details', 'woocommerce' ); ?></h2>
<table class="shop_table order_details">
<thead>
<tr>
<th class="product-name"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="product-total"><?php _e( 'Total', 'woocommerce' ); ?></th>
</tr>
</thead>
<tfoot>
<?php
if ( $totals = $order->get_order_item_totals() ) foreach ( $totals as $total ) :
?>
<tr>
<th scope="row"><?php echo $total['label']; ?></th>
<td><?php echo $total['value']; ?></td>
</tr>
<?php
endforeach;
?>
</tfoot>
<tbody>
<?php
if ( sizeof( $order->get_items() ) > 0 ) {
foreach( $order->get_items() as $item ) {
$_product = apply_filters( 'woocommerce_order_item_product', $order->get_product_from_item( $item ), $item );
$item_meta = new WC_Order_Item_Meta( $item['item_meta'], $_product );
?>
<tr class="<?php echo esc_attr( apply_filters( 'woocommerce_order_item_class', 'order_item', $item, $order ) ); ?>">
<td class="product-name">
<?php
if ( $_product && ! $_product->is_visible() )
echo apply_filters( 'woocommerce_order_item_name', $item['name'], $item );
else
echo apply_filters( 'woocommerce_order_item_name', sprintf( '%s', get_permalink( $item['product_id'] ), $item['name'] ), $item );
echo apply_filters( 'woocommerce_order_item_quantity_html', ' <strong class="product-quantity">' . sprintf( '× %s', $item['qty'] ) . '</strong>', $item );
$item_meta->display();
// insert product category here
$tax = 'product_cat';
$terms = wp_get_post_terms( $_product->id, $tax, array( 'fields' => 'names' ) );
if( $terms && ! is_wp_error( $terms )) {
$taxonomy = get_taxonomy($tax);
echo '<strong>' . $taxonomy->label . ': </strong>' . implode( ', ', $terms );
}
// end edit
if ( $_product && $_product->exists() && $_product->is_downloadable() && $order->is_download_permitted() ) {
$download_files = $order->get_item_downloads( $item );
$i = 0;
$links = array();
foreach ( $download_files as $download_id => $file ) {
$i++;
$links[] = '<small>' . sprintf( __( 'Download file%s', 'woocommerce' ), ( count( $download_files ) > 1 ? ' ' . $i . ': ' : ': ' ) ) . esc_html( $file['name'] ) . '</small>';
}
echo '<br/>' . implode( '<br/>', $links );
}
?>
</td>
<td class="product-total">
<?php echo $order->get_formatted_line_subtotal( $item ); ?>
</td>
</tr>
<?php
if ( $order->has_status( array( 'completed', 'processing' ) ) && ( $purchase_note = get_post_meta( $_product->id, '_purchase_note', true ) ) ) {
?>
<tr class="product-purchase-note">
<td colspan="3"><?php echo wpautop( do_shortcode( $purchase_note ) ); ?></td>
</tr>
<?php
}
}
}
do_action( 'woocommerce_order_items_table', $order );
?>
</tbody>
</table>
<?php do_action( 'woocommerce_order_details_after_order_table', $order ); ?>
<header>
<h2><?php _e( 'Customer details', 'woocommerce' ); ?></h2>
</header>
<dl class="customer_details">
<?php
if ( $order->billing_email ) echo '<dt>' . __( 'Email:', 'woocommerce' ) . '</dt><dd>' . $order->billing_email . '</dd>';
if ( $order->billing_phone ) echo '<dt>' . __( 'Telephone:', 'woocommerce' ) . '</dt><dd>' . $order->billing_phone . '</dd>';
// Additional customer details hook
do_action( 'woocommerce_order_details_after_customer_details', $order );
?>
</dl>
<?php if ( ! wc_ship_to_billing_address_only() && $order->needs_shipping_address() && get_option( 'woocommerce_calc_shipping' ) !== 'no' ) : ?>
<div class="col2-set addresses">
<div class="col-1">
<?php endif; ?>
<header class="title">
<h3><?php _e( 'Billing Address', 'woocommerce' ); ?></h3>
</header>
<address><p>
<?php
if ( ! $order->get_formatted_billing_address() ) _e( 'N/A', 'woocommerce' ); else echo $order->get_formatted_billing_address();
?>
</p></address>
<?php if ( ! wc_ship_to_billing_address_only() && $order->needs_shipping_address() && get_option( 'woocommerce_calc_shipping' ) !== 'no' ) : ?>
</div><!-- /.col-1 -->
<div class="col-2">
<header class="title">
<h3><?php _e( 'Shipping Address', 'woocommerce' ); ?></h3>
</header>
<address><p>
<?php
if ( ! $order->get_formatted_shipping_address() ) _e( 'N/A', 'woocommerce' ); else echo $order->get_formatted_shipping_address();
?>
</p></address>
</div><!-- /.col-2 -->
</div><!-- /.col2-set -->
<?php endif; ?>
<div class="clear"></div>