WC_Product_Variable_Data_Store_CPT::read_variation_attributes
Loads an array of attributes used for variations, as well as their possible values.
Method of the class: WC_Product_Variable_Data_Store_CPT{}
No Hooks.
Returns
array.
Usage
$WC_Product_Variable_Data_Store_CPT = new WC_Product_Variable_Data_Store_CPT(); $WC_Product_Variable_Data_Store_CPT->read_variation_attributes( $product );
- $product(WC_Product) (required) (passed by reference — &)
- Product object.
WC_Product_Variable_Data_Store_CPT::read_variation_attributes() WC Product Variable Data Store CPT::read variation attributes code WC 11.1.1
public function read_variation_attributes( &$product ) {
global $wpdb;
$product_id = $product->get_id();
$cache_key = WC_Cache_Helper::get_cache_prefix( 'product_' . $product_id ) . 'product_variation_attributes_' . $product_id;
$cached_data = wp_cache_get( $cache_key, 'products' );
if ( false !== $cached_data ) {
return $cached_data;
}
$variation_attributes = array();
$attributes = $product->get_attributes();
if ( ! empty( $attributes ) ) {
$child_ids = $product->get_children();
$attributes = array_values( array_filter( $attributes, static fn ( $attribute ) => ! empty( $attribute['is_variation'] ) ) );
$attributes_values = array();
if ( ! empty( $child_ids ) && ! empty( $attributes ) ) {
// Performance note: for optimal performance, retrieve attribute values using a single SQL query.
$attributes_placeholders = implode( ', ', array_fill( 0, count( $attributes ), '%s' ) );
$children_placeholders = implode( ', ', array_fill( 0, count( $child_ids ), '%d' ) );
$prefetch = $wpdb->get_results(
$wpdb->prepare(
// Performance: DISTINCT + CAST(meta_value AS BINARY(200)) is feasible but forces a temp table — keep array_unique.
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
"SELECT meta_key, meta_value FROM {$wpdb->postmeta} WHERE post_id IN ( {$children_placeholders} ) AND meta_key IN ( {$attributes_placeholders} )",
...$child_ids,
...array_map( static fn( $attribute ) => wc_variation_attribute_name( $attribute['name'] ), $attributes )
)
);
foreach ( $prefetch as $row ) {
// Defensive: normalize non-canonical meta_key casing (e.g. attribute_pa_Size → attribute_pa_size).
// sanitize_title over wc_variation_attribute_name as the latter adds 'attribute_' prefix.
$attributes_values[ sanitize_title( $row->meta_key ) ][] = $row->meta_value;
}
}
foreach ( $attributes as $attribute ) {
$values = $attributes_values[ wc_variation_attribute_name( $attribute['name'] ) ] ?? array();
// Empty value indicates that all options for given attribute are available.
if ( empty( $values ) || in_array( null, $values, true ) || in_array( '', $values, true ) ) {
$values = $attribute['is_taxonomy'] ? wc_get_object_terms( $product_id, $attribute['name'], 'slug' ) : wc_get_text_attributes( $attribute['value'] );
// Get custom attributes (non taxonomy) as defined.
} elseif ( ! $attribute['is_taxonomy'] ) {
$text_attributes = wc_get_text_attributes( $attribute['value'] );
$assigned_text_attributes = $values;
$values = array();
// Pre 2.4 handling where 'slugs' were saved instead of the full text attribute.
if ( version_compare( get_post_meta( $product_id, '_product_version', true ), '2.4.0', '<' ) ) {
$assigned_text_attributes = array_map( 'sanitize_title', $assigned_text_attributes );
foreach ( $text_attributes as $text_attribute ) {
if ( in_array( sanitize_title( $text_attribute ), $assigned_text_attributes, true ) ) {
$values[] = $text_attribute;
}
}
} else {
foreach ( $text_attributes as $text_attribute ) {
if ( in_array( $text_attribute, $assigned_text_attributes, true ) ) {
$values[] = $text_attribute;
}
}
}
}
$variation_attributes[ $attribute['name'] ] = array_unique( $values );
}
}
wp_cache_set( $cache_key, $variation_attributes, 'products' );
return $variation_attributes;
}