Productafbeeldingen in bulk verwijderen (PHP-API)
Hoe kun je geautomatiseerd in bulk productafbeeldingen verwijderen van een site? Dus:
- Associatie tussen afbeeldingen en producten verwijderen
- Afbeeldingen verwijderen uit de media-bibliotheek
- Extra: Afbeeldingen verwijderen uit het bestandssysteem.
Dit vraagstuk ontstond rond 2018/2019 voor het eerst, toen ik begon met geautomatiseerd vullen van een site: Vanwege het vele experimenteren, zou het prettig zijn als dat vullen ook weer ongedaan zou kunnen worden gemaakt. In april 2021 werd deze vraag opnieuw actueel: Voor een bestaande webwinkel wil ik het aantal afbeeldingen verminderen, door een hoop producten dezelfde afbeelding te laten gebruiken (BrushTour, post ch_fr, redim-php). Dat lijkt het handigste te gaan, als ik eerst de bestaande afbeeldingen kan verwijderen.
wp_delete_attachment (PHP-API)
Vermoedelijk is dit de standaard-routine om attachments te verwijderen. De officiële documentatie [1] is mij niet helemaal duidelijk:
When an attachment is permanently deleted, the file will also be removed. Deletion removes all post meta fields, taxonomy, comments, etc. associated with the attachment (except the main post). The attachment is moved to the Trash instead of permanently deleted unless Trash for media is disabled, item is already in the Trash, or $force_delete is true.
Wat ik dankzij de voorbeelden/tests hieronder heb achterhaald:
- Dit commando heeft niets met WooCommerce-producten te maken. Het opereert uitsluitend op attachments (afbeeldingen in mijn geval). De acties van dit commando hebben daarom ook niets met WooCommerce-producten te maken
- Wat dit commando doet: Alsof je zelf in de media-bibliotheek bestanden verwijderd (en die tevens op een nette manier verwijderd van de posts of objecten waarmee deze zijn geassocieerd)
- Als je
$force_delete = True
meegeeft, worden de bestanden verwijderd. Anders blijven ze behouden - Ik weet niet wat er bedoeld wordt met de uitleg (except the main post)
Voorbeeld (1)
Voor een bestaand product gebruik ik wp_attachment_delete
om de bijbehorende thumbnail-afbeelding weg te toveren.
Oude situatie
Code
<?php # # Test wp_delete_attachment() ################################################################################ # $site_path = "/var/www/knl.s1"; require_once($site_path . "/wp-load.php"); wp_delete_attachment(39019);
Nieuwe situatie
Voorbeeld (2)
- Nu zowel de thumbnail- als gallerij-afbeelding van een product verwijderen
- Direct verwijderen - Zonder prullenpak.
Oude situatie
Code om de afbeeling-ID's te achterhalen:
use knl_s1; select wp_posts.ID as product_id, wp_posts.post_title as product_title, wp_postmeta.* from wp_postmeta join wp_posts on wp_postmeta.post_id = wp_posts.ID where wp_posts.post_type like 'product' and wp_posts.post_title like "%27919%" and ( wp_postmeta.meta_key like '_thumbnail_id' or wp_postmeta.meta_key like '_product_image_gallery' )
Code
<?php # # Test wp_delete_attachment() ################################################################################ # # * Both thumbnail & gallery images # * Sidepass trash # * Image file: http://knl.s1/wp-content/uploads/2020/09/4956_logo_01.jpg # * First gallery file: http://knl.s1/wp-content/uploads/2020/09/4956_logo_02.jpg # $site_path = "/var/www/knl.s1"; require_once($site_path . "/wp-load.php"); wp_delete_attachment(54858, True); wp_delete_attachment(54859, True); wp_delete_attachment(54860, True); wp_delete_attachment(54861, True);
Nieuwe situatie
Bronnen
- https://stackoverflow.com/questions/43329403/programmatically-delete-images-from-wordpress
- https://developer.wordpress.org/reference/functions/wp_delete_attachment
dvb_delete_all_thumbnails
Rond 2019 dit PHP-script geschreven. Het maakt gebruik van $wpdb
(db-layer) en is eigenlijk niet meer dan een veredeld database-script.
Hoe het werkt
- Verzamel in een tijdelijke tabel de post-id's van alle afbeeldingen die als thumbnail gebruikt worden
- Verwijder uit tabel
wp_posts
alle posts met deze id's - Verwijder alle entries uit
wp_postmeta
voor deze id's.
Beperkingen
- Afbeeldingen worden verwijderd als ze als product-thumbnail worden gebruikt. Ongeacht of afbeeldingen daarnaast ook op andere manieren worden gebruikt
- Gallery-afbeeldingen worden niet verwijderd
- De afbeeldingen worden niet verwijderd uit het bestandssyteem.
Overig
De routine is snel, want de eigenlijke functionaliteit is afgebeeld in SQL en niet in PHP. In april 2021 toegepast op een webshop met zo'n 15.000 producten. Het script was binnen een minuut klaar.
Voorbeeld
SQL
Dit zijn de vier SQL-statements in deze functie. Met toegevoegde indentatie & commentaar:
sql_01
drop table if exists wp_image_tmp;
sql_02
# Collect the post_IDs from images that are used for products and # have property "_thumbnail_id" ###################################################################### # create temporary table wp_image_tmp select wp_postmeta.meta_value as image_id from wp_postmeta join wp_posts on wp_postmeta.post_id = wp_posts.ID where wp_posts.post_type like 'product' and wp_postmeta.meta_key like '_thumbnail_id';
sql_03
# Delete the posts with these post-ids ###################################################################### # delete wp_posts from wp_posts join wp_image_tmp on wp_posts.ID = wp_image_tmp.image_id;
sql_04
# Delete all wp_postmeta entries for these post-ids ###################################################################### # delete wp_postmeta from wp_postmeta join wp_image_tmp on wp_postmeta.post_id = wp_image_tmp.image_id;
Script
####################################################################################### # dvb_delete_all_thumbnails ####################################################################################### # # Removes images that are associated with products as thumbnails # # * Only thumbnails - No gallery-related images # * Only thumbnails - If an image is used for mutiple purposes (e.g., site logo), it # will be removed # * Images won't be removed from the upload-directory - Keep it simple # * When deleting both images and products, delete images first! Once they're not # thumbnails anymore, images won't be deleted anymore # * This script should be called from another PHP-script, where the PHP-API from the # relevant site has already been initiated. That's why this function # dvb_delete_all_thumbnails doesn't take arguments # * It's quite impractical that this script has to be called from another script: # It actually means that from a command line, I call that other script, that calls # this script - Not intuitive at all. # function dvb_delete_all_thumbnails() { # Access ###################################### # # require_once($pad . "wp-load.php"); # global $wpdb; # Assemble queries ###################################### # $sql_01 = "drop table if exists ".$wpdb->prefix."image_tmp;"; $sql_02 = "create temporary table ".$wpdb->prefix."image_tmp select ".$wpdb->prefix."postmeta.meta_value as image_id from ".$wpdb->prefix."postmeta join ".$wpdb->prefix."posts on ".$wpdb->prefix."postmeta.post_id = ".$wpdb->prefix."posts.ID where ".$wpdb->prefix."posts.post_type like 'product' and ".$wpdb->prefix."postmeta.meta_key like '_thumbnail_id';"; $sql_03 = "delete ".$wpdb->prefix."posts from ".$wpdb->prefix."posts join ".$wpdb->prefix."image_tmp on ".$wpdb->prefix."posts.ID = ".$wpdb->prefix."image_tmp.image_id;"; $sql_04 = "delete ".$wpdb->prefix."postmeta from ".$wpdb->prefix."postmeta join ".$wpdb->prefix."image_tmp on ".$wpdb->prefix."postmeta.post_id = ".$wpdb->prefix."image_tmp.image_id;"; # Ready to go? ###################################### # // echo "\nsql_01: ".$sql_01; // echo "\nsql_02: ".$sql_02; // echo "\nsql_03: ".$sql_03; // echo "\nsql_04: ".$sql_04."\n"; # Go! ###################################### # try { $wpdb->query($sql_01); $wpdb->query($sql_02); $wpdb->query($sql_03); $wpdb->query($sql_04); } catch(Exception $e){} }