Update all objects in a set (WP-CLI)

Uit De Vliegende Brigade
Naar navigatie springen Naar zoeken springen

One thing, that sometimes seems suprisingly difficult to do with WP-CLI:

Update a given property for all objects of a certain type

or

Update a given property for all objects in a set

However, this isn't an issue at all. This article is to get clear what makes this sometimes an issue, and sometimes not.

Example: Update reviews_allowed for all products

This is an example of something that is ridiciously hard to do.

The problem

  • WooCommerce site with 17.449 products
  • For most products, the general property reviews_allowed is set, but for a minority of products, this isn't set
  • Let's set this property
  • Test: Have a way to compare the situation before and after, to make sure it's done.

How to do this - In theory

  • Get a list of products where this property is not set
  • Update this property for all these products
  • Check again to see that it is done correctly.

How to do this - In practice

Step 1: Get the list of products where this property isn't set

  • I Can use wp wc product list to get the ids of all products, but this is quite hard to do for 17,000 products. See Wp wc product list for a script that thanks to Gnu Parallel, manages to do this in only about 8 minutes
  • But this is the list of all products. With wp wc product list, I can't retrieve a list of product where this property isn't set
  • I also can't easily filter this list afterwards: Theoretically, I could get an associative array with both ids and the value for this property, but that's actually what databases are for, and it already comes out of a database.

Conclusion: This can't reasonably be done. Fortunately, in this situation having a list of just the ids, is also quite ok - but it does mean I can't easily check.

Step 2: Update all products in this set

  • There isn't a command to update objects in bulk: wp wc product list can only list, and wp wc product update only updates one product at a time
  • I can use the set of ids from Step 1 (stored in an array) as input for wp wc product update, but it will probably take a lot of time

Conclusions

  • It can only partially do what was described
  • It takes some serious programming
  • Execution takes a lot of time
  • Because it is so convoluted, it's error prone.

To put it differently: It takes a day to do this, and actually a really good day, for it is very precisely work.

In SQL

This is how I could do the entire job in SQL:

# Check old situation
########################################
#
select count (*) from wp_posts where post_type="product" and comment_status="closed";
select id, post_name from wp_posts where post_type="product" and comment_status="closed";


# Update
########################################
#
update wp_posts set comment_status="open" where post_type="product" and comment_status="closed";


# Check new situation
########################################
#
select count (*) from wp_posts where post_type="product" and comment_status="closed";
select id, post_name from wp_posts where post_type="product" and comment_status="closed";

and it takes less than a second. I could use wp db query to make this a bit more robust.

Why this SQL approach is so much better:

  • Much shorter
  • The code is very easy to comprehend
  • Can be programmed in 5 minutes
  • Probably at least 100 times faster
  • Results are easy to check
  • Results are easy to comprehended.

What's the problem here with WP-CLI?

I think the actual problem is, that wp wc product list doesn't have the ability to filter on values of specific attributes. If this would have been possible, stuff would have already been a lot easier:

  • I could select only the records that I need - Making it easier to check if the process goes well, as I would simply execute the same command at the end of the procedure
  • Subsequent computation time would be much less