Filtrovanie produktov podľa dostupnosti a atribútov na úrovni variánt

Filtrovanie produktov je neoddeliteľnou súčasťou každého e-shopu, zvlášť v prípade veľkého počtu produktov, variánt a ich vlastností (atribútov). Wocommerce ponúka pomerne jednoduchý spôsob filtrovania produktov na základe jendotlivých vlastností. Napríklad, ak na e-shope predávame tričká s variantami na základe vlastnosti veľkosť, môžeme si jednoducho vyfiltrovať všetky tričká s veľkosťou M a zobrazia sa nám všetky produkty, ktoré obsahujú aspoň jednu variantu s touto veľkosťou. Ak sa k tomuto filtrovaniu pridá možnosť vyfiltrovať iba produkty, ktoré sú skladom, dochdáza k problému, keďže Woocommerce pri filtrovaní produktov kontroluje dostupnosť iba na úrovni parent produktu a nie na úrovni variánt. Preto sa medzi vyfiltrované produkty dostanú aj tie, ktoré síce majú variantu s veľkosťou M avšak sú vypredané, čo je nesprávne a pre zákazníka mätúce. Viac o tomto probléme sa dočítate v tomto príspevku. Nižšie priložený kód skontroluje skladovú dostupnosť na úrovni variánt v prípade filtrovania produktov na základe vlastností a dostupnosti. Ide iba o čiastočné riešenie problému, keďže dochádza ku filtrovaniu už získaných produktov a teda môže dochádzať k nesprávnemu zobrazovaniu počtu produktov a pod.

				
					//hide in posts results
add_filter( 'posts_results', 'px_posts_results_filter' );
function px_posts_results_filter( $posts ) {

	$filtered_posts = [];

	$attributes = [];

	$attribute_taxonomies = wc_get_attribute_taxonomies();

	foreach ($attribute_taxonomies as $attribute_taxonomy) {
		$attributes[] = $attribute_taxonomy->attribute_name;
	}

	if ( ! is_admin() && ( is_shop() || is_product_category() || is_product_taxonomy() ) ) {

		if ( ! empty( $_GET['stock_status'] ) ) {

			$stock_status = explode( ',', $_GET['stock_status'] );

			//only if parameter stock_status contain instock
			if ( in_array( 'instock', $stock_status ) ) {

				$filter_array = px_get_filter_parameter_values( $attributes );

				//only if set same filter parameters by attributes
				if ( ! empty( $filter_array ) ) {

					foreach ( $posts as $post ) {

						$product_id = $post->ID;

						$variation_ids = px_get_variations_by_attributes( $product_id, $filter_array );

						if ( ! empty( $variation_ids ) ) {
							foreach ( $variation_ids as $variation_id ) {
								$product_variation = wc_get_product( $variation_id );

								if ( $product_variation->is_in_stock() ) {

									//$filtered_posts[$variation_id] = get_post($variation_id); //Add variation post

									$filtered_posts[ $product_id ] = $post; //Add parent product
								}
							}

						}


					}
				}

			}
		}
	}

	if ( ! empty( $filtered_posts ) ) {
		return array_values( $filtered_posts );
	} else {
		return $posts;
	}

}

//helpers
function px_get_filter_parameter_values( $attributes ): array {
	$filter_array = [];
	foreach ( $attributes as $attribute ) {
		$parameter_name = "filter_" . $attribute;

		if ( isset( $_GET[ $parameter_name ] ) ) {
			$attribute_values           = explode( ',', $_GET[ $parameter_name ] );
			$filter_array[ $attribute ] = $attribute_values;
		}
	}

	return $filter_array;
}

function px_get_variations_by_attributes( $product_id, $attributes ): array {
	$product = wc_get_product( $product_id );

	$variation_ids = [];

	if ( $product->get_type() == 'variable' ) {

		$variations = $product->get_available_variations();

		if ( $variations ) {

			foreach ( $variations as $variation ) {

				$is_match_variation = true;
				foreach ( $attributes as $attribute_key => $attribute_values ) {
					$variation_attribute_value = $variation['attributes'][ 'attribute_pa_' . $attribute_key ] ?? [];

					//if only one from attributes is not match stop
					if ( ! in_array( $variation_attribute_value, $attribute_values ) ) {
						$is_match_variation = false;
						break;
					}

				}

				if ( $is_match_variation ) {
					$variation_ids[] = $variation['variation_id'];
				}

			}
		}

	}

	return $variation_ids;
}
				
			
Picture of Roman Kraiger

Roman Kraiger

Zakladateľ agentúry Pixeler, vášnivý cyklista, programátor a občasný bloger.

Páčil sa Vám tento článok?

Odmeňte ho páčikom.

alebo ho zdieľajte medzi priateľmi na:

Pridaj komentár

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *