WooCommerce – přidání polí do detailu produktu

Web autonalepky.cz, který prodává nálepky na auta, potřeboval vytvořit specifickou funkcionalitu – při importu produktů zjistit velikost obrázku ve formátu svg, uložit poměr stran, v detailu produktu pak zobrazovat přesné rozměry nálepek dle poměru stran, a dle toho počítat cenu.

Taková funkcionalita by samozřejmě šla zařídit variantami produktů, ale vzhledem k počtu produktů na eshopu (více než 3500) a množství variací (5 velikostí pro každý produkt) jsem se rozhodl pro programování na míru.

Jedním z kroků pro tuto funkcionalitu je zobrazování custom polí v detailu produktu. Něco podobného je poměrně častý požadavek, a níže je pro inspiraci kód, který to zařídí.
Kód postupně přidá pole k detailu produktu, uloží extra data do WooCommerce session, zobrazí je v košíku a pokladně, a uloží je jako metadata k jednotlivým položkám.

Hodnoty, které zákazník vybral, se pak automaticky zobrazují v administrace, všech emailech atd.

Jak to funnguje v praxi se můžete podívat na webu autonalepky.cz


<?php

namespace Autonalepky;

class WooCommerce {
	function __construct() {
	}

	function initialize() {
		add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'product_details' ) );
		add_filter( 'woocommerce_add_cart_item_data', array( $this, 'add_custom_cart_item_data' ), 10, 3 );
		add_action( 'woocommerce_add_order_item_meta', array( $this, 'add_order_item_meta' ), 10, 2 );
		add_filter( 'woocommerce_get_item_data', array( $this, 'get_custom_cart_item_data' ), 10, 2 );
	}

	/**
	 * Display the custom product details
	 */
	function product_details() {
		/** @var $product \WC_Product */
		global $product;

		$sizes    = $this->get_product_sizes( $product->get_id() );
		$variants = $this->get_variants( $product->get_id() );

		?>

        <div>
			<?php if ( in_array( '1', $variants ) ): ?>
                <p>
                    <label for="size"><?php _e( 'Size', AN_TEXTDOMAIN ); ?></label>
                    <select name="size" id="size" required="required">
						<?php foreach ( $sizes as $size ) { ?>,
                            <option value="<?php echo $size['width'] . 'x' . $size['height']; ?>"><?php echo str_replace( '.', ',', $size['width'] ) . ' x ' . str_replace( '.', ',', $size['height'] ); ?> cm</option>
						<?php } ?>
                    </select>

                </p>
			<?php endif; ?>
			<?php if ( in_array( '2', $variants ) ): ?>
                <p>
                    <label for="color"><?php _e( 'Color', AN_TEXTDOMAIN ); ?></label>
                    <select name="color" id="color" required="required">
						<?php foreach ( $this->get_colors() as $color ) { ?>
                            <option value="<?php echo $color['id']; ?>" data-color="<?php echo $color['color']; ?>"><?php echo $color['name']; ?></option>
						<?php } ?>
                    </select>
                </p>
			<?php else: ?>
                <input type="hidden" name="color" value="as-is">
			<?php endif; ?>
			<?php if ( in_array( '3', $variants ) ): ?>
                <p>
                    <label for="inverse"><?php _e( 'Inverse', AN_TEXTDOMAIN ); ?></label>
                    <select name="inverse" id="inverse">
                        <option value="none"><?php _e( 'As is', AN_TEXTDOMAIN ); ?></option>
                        <option value="horizontally"><?php _e( 'Flip horizontally', AN_TEXTDOMAIN ); ?></option>

                    </select>
                </p>
			<?php endif; ?>
            <input type="hidden" name="product_id" value="<?php echo $product->get_id(); ?>"/>

        </div>
	<?php }

	/**
	 * Save the cart item data to the session
	 *
	 * @param $cart_item_data
	 * @param $product_id
	 * @param $variation_id
	 *
	 * @return mixed
	 */
	function add_custom_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
		$cart_item_data['size'] = filter_input( INPUT_POST, 'size' );;
		$cart_item_data['color']   = filter_input( INPUT_POST, 'color' );
		$cart_item_data['inverse'] = filter_input( INPUT_POST, 'inverse' );;

		return $cart_item_data;
	}

	/**
	 * Display the cart item data on cart and checkout
	 *
	 * @param $item_data
	 * @param $cart_item
	 *
	 * @return array
	 */
	function get_custom_cart_item_data( $item_data, $cart_item ) {
		$item_data[] = array(
			'key'     => __( 'Color', AN_TEXTDOMAIN ),
			'value'   => wc_clean( $cart_item['color'] ),
			'display' => $cart_item['color']
		);

		$item_data[] = array(
			'key'     => __( 'Size', AN_TEXTDOMAIN ),
			'value'   => wc_clean( $cart_item['size'] ),
			'display' => wc_clean( $cart_item['size'] ),
		);

		$item_data[] = array(
			'key'     => __( 'Inverse', AN_TEXTDOMAIN ),
			'value'   => wc_clean( $cart_item['inverse'] ),
			'display' => wc_clean( $cart_item['inverse'] )
		);

		return $item_data;
	}

	/**
     * Save the extra data to the item
	 * @param $item_id
	 * @param $values
	 */
	function add_order_item_meta( $item_id, $values ) {
		$wc     = new WooCommerce();
		$colors = $wc->get_colors();

		$inverse = $values['inverse'] == 'none' ? __( "Don't inverse", AN_TEXTDOMAIN ) : __( "Flip horizontally", AN_TEXTDOMAIN );
		wc_add_order_item_meta( $item_id, __( 'Color', AN_TEXTDOMAIN ), $colors[ $values['color'] ]['name'] );
		wc_add_order_item_meta( $item_id, __( 'Size', AN_TEXTDOMAIN ), $values['size'] );
		wc_add_order_item_meta( $item_id, __( 'Inverse', AN_TEXTDOMAIN ), $inverse );
	}
}

$WooCommerce = new WooCommerce();
$WooCommerce->initialize();

 

1 Comment

  1. Robert Šperka - Autonálepky.cz on 13.9.2018 at 23:34

    Dlouhou dobu jsem hledal programátora, který by dokázal vytvořit e-shop dle mých představ za rozumných logických podmínek. Věděl jsem přesně co chci a jak to chci udělat. Nevěřil jsem, že na Woocommerce to dokážeme. Václav Greif, byl jediný, který pochopil mou problematiku a zároveň jednoduchost řešení. Díky němu jsem dosáhl optimálního výsledku, který jsem si představoval. A funguje to 😉 Mohu jen doporučit. Dokáže se vžít do problematiky a logicky ji řešit.

Přidat komentář