Updating WooCommerce Product Dimensions Programmatically

Recently, I needed to update all of the products in a WooCommerce store. The dimensions were included in every product name but I needed them to be set as the product dimensions. If there were only a dozen or so products, manually editing them would be an option but this store has around 7 thousand. Manually doing this would be error prone and take a lot of time. So I wrote a quick script to automatically add the dimensions. Here’s how that works.

The first step is to get a list of the products. To limit potential complications, I decided to do this one category at a time. That way I could roll out the changes incrementally. WooCommerce gives us the wc_get_products() method that we can use to load a list of products by category. Here’s what that looks like:

function update_dimensions( $cat ) {
	$args = array(
		'category' => array( $cat ),
		'orderby'  => 'id',
		'limit'    => 800,
	);

	$products = wc_get_products( $args );

The idea here is to pass the slug for the product category into the function (that’s the $cat argument). The “limit” here sets the maximum number of products that can be returned. By default, 10 are returned so I set this much higher than the category with the most products to make sure none were missed.

Now with a foreach loop, I can examine the name of each product and update the dimensions if they meet certain criteria. Here’s the code I’m using for that:

		foreach ( $products as $product ) {

			foreach ( $widths as $width ) {
				if ( matches_pattern( $width['pattern'], $product->get_name() ) ) {
					$product->set_width( $width['dimension'] );
					$product->save();
					error_log( 'updated product width ' . $width['dimension'] . ' ' . $product->get_name() );
				}
			}

			foreach ( $heights as $height ) {
				if ( matches_pattern( $height['pattern'], $product->get_name() ) ) {
					$product->set_height( $height['dimension'] );
					$product->save();
					error_log( 'updated product height ' . $height['dimension'] . ' ' . $product->get_name() );
				}
			}
		}

Each product is run through two more loops to check the width and height of the title. It has the pattern I’m trying to match as well as the value I want to set. There were lots of them so I’m leaving most of them out but here’s an example so you’ll have an idea.

$widths = array(
	'60'   => array(
		'pattern'   => '/ 60"W /i',
		'dimension' => 60,
	),
);

To determine if there is a match, I have a helper method called matches_pattern() that I’m using. It takes the $pattern and the text $string and compares them through PHP’s preg_match method. If they match, the number of matches is returned. Otherwise, false is sent back.

function matches_pattern( $pattern, $string ) {
		return preg_match( $pattern, $string );
	}

The dimensions are updated in this block. It checks for the match and if it exists, it’ll update the dimension to the new value and save the product. I’ve also included a log statement here to give me a record of what happened in case there are problems.

if ( matches_pattern( $height['pattern'], $product->get_name() ) ) {
	$product->set_height( $height['dimension'] );
	$product->save();
	error_log( 'updated product height ' . $height['dimension'] . ' ' . $product->get_name() );
}

And that’s about it. Nesting foreach loops can be a bit risky since they can consume so many resources. Since we have a limit on the number of products, this runs rather quickly. In my testing, I could update about 300 products in two to three seconds.

While I’m doing this with dimensions, you could update other product properties in the same way. It’s a good option to consider if you need to change a large number of products. Plus since we’re using WooCommerce’s native product methods, this will continue to work even if products are migrated to different database tables in the future.

Also, I ended up setting this up inside a class with the update_dimensions() method being a public static function. That way I can easily access it from anywhere without having to create an instance of the class. But it’s perfectly fine to use these outside of a class too.

If you have any interesting use cases for this or any questions, let me know in the comments.


Leave a Reply

%d bloggers like this: