
🗑 WordPress meediateegi programmiline puhastamine: PHP skriptid rämpsfailide eemaldamiseks
WordPressi meediumikogu töötab nagu pööning: kustutad postituse, pildid jäävad alles. Vahetad teemat, vanad pildisuurused istuvad surnud raskusena. Migreerid saiti, pooled pisipildid annavad 404 vea.
Käsitsi puhastamine läbi adminpaneeli saidil, kus on paar tuhat faili, on meditatsiooniharjutus. Kuid on kiirem viis: viis PHP funktsiooni, mis leiavad ja eemaldavad rämpsu ühe käiguga. Ilma pluginateta, selge koodi ja kontrolliga iga kustutatud faili üle.
Enne käivitamist tee täielik varukoopia. Need funktsioonid kustutavad failid jäädavalt: ei mingeid prügikaste ega tagasivõtmist. Kahtluse korral käivita esmalt testkeskkonna koopial.
💡 Kiirülevaade:
- Kustutab sidumata manused, failid, mis jäid pärast postituse kustutamist alles
- Puhastab meediumifailid kindlast kohandatud postitüübist (CPT)
- Puhastab meediumikogu katkistest linkidest, 404 manustest, millel pole serveris faili
- Leiab ja kustutab failid kaustast
wp-content/uploads, mis pole registreeritud WordPressi manustena - Stsenaarium saitidele, kus pildid on salvestatud kohandatud väljadel (ACF, Meta Box), mitte manustena
Mida pead enne käivitamist teadma
Allolev kood kustutab faile füüsiliselt, nii kettalt kui andmebaasist. Kolm asja, mis su saidi päästavad.
Esiteks: pildid märgendite arhiivilehtedel või SEO kirjeldustes pole sageli ühegi postitusega seotud. Need ripuvad „orbudena", kuid sait vajab neid. Kui sul on selliseid pilte, jäta need nende funktsioonide ulatusest välja või kohanda tingimusi.
Teiseks: WordPress loob igast pildist mitu suurust. Pisipildid pärivad originaali post_parent väärtuse, seega funktsioon delete_unattached_attachments() neid ei puuduta, see filtreerib rangelt tingimusega post_parent = 0. Probleem tekib ainult siis, kui originaal ise on kaotanud oma seose postitusega.
Kolmandaks: kui postituse sisus on link kustutatud failile, siis see link puruneb pärast puhastamist. Enne käivitamist indekseeri sait Screaming Frog või sarnase tööriistaga ja kaardista lingid.
1. Sidumata manuste kustutamine
Kõige tavalisem stsenaarium: kustutasid postituse, manused jäid andmebaasi alles parameetritega post_type = 'attachment' ja post_parent = 0. Need võtavad ruumi nii kettal kui varukoopiates.
Allolev funktsioon leiab kõik sellised kirjed ja kustutab need. Paiguta see alamteema functions.php faili või kasuta koodijupi pluginat nagu WPCode. See ei käivitu iseenesest, see on definitsioon, mis vajab väljakutset.
1 function delete_unattached_attachments() { 2 $attachments = get_posts( array( 3 'post_type' => 'attachment', 4 'numberposts' => -1, 5 'fields' => 'ids', 6 'post_parent' => 0, 7 ) ); 8 9 if ( $attachments ) { 10 foreach ( $attachments as $attachment_id ) { 11 $attachment_path = get_attached_file( $attachment_id ); 12 wp_delete_attachment( $attachment_id, true ); 13 unlink( $attachment_path ); 14 } 15 } 16 }
get_posts() valib kõik manused, millel pole vanempostitust. wp_delete_attachment() parameetriga true kustutab nii andmebaasikirje kui ka faili koos pisipiltidega. Täiendav unlink() on kindlustus: kui fail jäi mingil põhjusel kettale, kustutatakse see sunniviisiliselt.
Märkus: esiletõstetud piltidel on mõnes konfiguratsioonis samuti post_parent = 0. Enne tootmiskeskkonnas käivitamist asenda wp_delete_attachment koodiga echo $attachment_id . '<br>', näed nimekirja ID-dest, mis kustutatakse. Kui oled veendunud, et kõik on korrektne, taasta tootmisversioon.
Pärast ühekordset käivitamist eemalda funktsioon failist functions.php. Pole vaja seda iga init käigus alles hoida.
2. Kindla CPT manuste kustutamine
Endine WooCommerce'i pood, vana portfoolio sektsioon, kustutatud kohandatud postitüüp, kõik nende pildid istuvad endiselt serveris. Allolev funktsioon puhastab määratud tüüpi postitustega seotud manused.
1 function delete_cpt_attachments( $cpt = 'card' ) { 2 $attachments = get_posts( array( 3 'post_type' => 'attachment', 4 'numberposts' => -1, 5 ) ); 6 7 if ( $attachments ) { 8 foreach ( $attachments as $attachment ) { 9 $parent_id = $attachment->post_parent; 10 11 if ( $cpt === get_post_type( $parent_id ) ) { 12 $attachment_path = get_attached_file( $attachment->ID ); 13 wp_delete_attachment( $attachment->ID, true ); 14 unlink( $attachment_path ); 15 } 16 } 17 } 18 }
Asenda 'card' oma CPT tunnusega. WooCommerce'i toodete puhul 'product'. Kui CPT on juba kustutatud, tagastab get_post_type() väärtuse false, selle tüübi manuseid see ei mõjuta. Kustutatud CPT-de puhul tuleb loogikat kohandada: kontrolli mitte vanema tüüpi, vaid kuuluvust taksonoomiasse või metavälja.
Suurte andmebaaside puhul ole ettevaatlik: 'numberposts' => -1 ilma 'fields' => 'ids' laeb täielikud WP_Post objektid. 10 000+ manuse puhul võib see ületada memory_limit piirangu. Tootmismahtude jaoks lisa 'fields' => 'ids' ja küsi ainult ID-sid, get_post_type() töötab ka vanemate ID-dega.
3. Meediumikogu puhastamine 404 manustest
Katkised pisipildid meediumikogus on sümptom, et fail kettal on kustutatud (käsitsi, hostingu rikke või vigase plugina tõttu), kuid andmebaasikirje jäi alles. WordPress näitab halli ristkülikut, kuid klikkides avaneb 404.
Funktsioon pärib iga manuse URL-i ja kustutab need, mis tagastavad 404.
1 function delete_404_attachments() { 2 $attachments = get_posts( array( 3 'post_type' => 'attachment', 4 'numberposts' => -1, 5 'fields' => 'ids', 6 ) ); 7 8 if ( $attachments ) { 9 foreach ( $attachments as $attachment_id ) { 10 $file_url = wp_get_attachment_url( $attachment_id ); 11 $file_headers = @get_headers( $file_url ); 12 13 if ( $file_headers && strpos( $file_headers[0], '404' ) !== false ) { 14 wp_delete_attachment( $attachment_id, true ); 15 } 16 } 17 } 18 }
Oluline: see funktsioon on ressursimahukas. Iga get_headers() kutse on HTTP päring sinu enda serverisse. Tuhande manuse puhul teed ühe käiguga tuhat HTTP päringut. Tulemus: aeglane, serveri koormus, mõned hostinguteenuse pakkujad katkestavad protsessi ajalõpu tõttu.
Suurte meediumikogude puhul jaga töö tükkideks, kasutades 'offset' ja 'numberposts' parameetreid, või käivita WP-CLI kaudu pakipiiranguga. Kui sait on CDN-i või puhverserveri taga, asenda kontroll funktsiooniga wp_remote_head() koos ajalõpuga, get_headers() ei käsitle alati ümbersuunamisi õigesti ega toeta autentimist.
4. Vastupidine kontroll: failid üleslaadimiste kaustas ilma andmebaasikirjeta
Kolm eelmist funktsiooni puhastavad andmebaasi, kustutavad manuste kirjeid. Kuid wp-content/uploads võib sisaldada faile, mis pole üldse manustena registreeritud: üles laaditud FTP kaudu, pluginatest maha jäänud, vahemälu genereeritud.
See funktsioon läheb vastupidist teed: mitte andmebaasist failideni, vaid failidest andmebaasi. Skaneerib rekursiivselt kausta wp-content/uploads ja kontrollib iga faili puhul funktsiooniga attachment_url_to_postid(), kas see on manus. Kui ei ole, siis kustutab selle.
1 function clean_uploads_from_nonattachments() { 2 $uploads_dir = wp_upload_dir(); 3 $search = $uploads_dir['basedir']; 4 $replace = $uploads_dir['baseurl']; 5 $root = $uploads_dir['basedir']; 6 7 $iter = new RecursiveIteratorIterator( 8 new RecursiveDirectoryIterator( $root, RecursiveDirectoryIterator::SKIP_DOTS ), 9 RecursiveIteratorIterator::SELF_FIRST, 10 RecursiveIteratorIterator::CATCH_GET_CHILD 11 ); 12 13 foreach ( $iter as $fileinfo ) { 14 if ( $fileinfo->isFile() ) { 15 $image_path = $fileinfo->getPathname(); 16 $image_url = str_replace( $search, $replace, $image_path ); 17 $attachment_id = attachment_url_to_postid( $image_url ); 18 19 if ( ! $attachment_id ) { 20 unlink( $image_path ); 21 } 22 } 23 } 24 }
Testserveris, kus üleslaadimisi oli 1 GB, töötas funktsioon 15 sekundit ja vabastas 700 MB, jättes alles 300 MB tegelikult kasutatavaid faile. Üle 5 GB suuruste kaustade puhul jaga skaneerimine aastate kaupa: asenda $root väärtusega $uploads_dir['basedir'] . '/2025/', seejärel '/2024/' ja nii edasi.
Esmalt käivita versioon ilma kustutamiseta, asenda unlink( $image_path ) koodiga echo $image_path . PHP_EOL. Näed täielikku nimekirja failidest, mida funktsioon rämpsuks peab. Kontrolli visuaalselt, seejärel taasta unlink().
5. Stsenaarium kohandatud väljadega: kui pildid pole manused
Kõige keerulisem juhtum: sait, kus pildid pole salvestatud WordPressi manustena, vaid URL-idena kohandatud väljadel (ACF, Meta Box, kohandatud teemaväljad). Tüüpiline näide, raamatupood: raamatu kaas väljal bookcover, autori foto väljal bookauthor_picture, nimekirja pilt väljal book_list_pictrue.
Sellise arhitektuuri puhul tagastab attachment_url_to_postid() kõigi üleslaadimiste failide puhul 0. Eelmine funktsioon kustutab kõik, sealhulgas tegelikult kasutatavad pildid. Vaja on teistsugust lähenemist.
5.1. Valge nimekirja koostamine
Esmalt kogu kõikide vajalike kohandatud väljade piltide URL-id. Allolevas näites on kolm CPT-d ja kolm välja:
1 $all_good_pictures = array(); 2 3 // Book covers (CPT 'post', field 'bookcover') 4 $posts = get_posts( array( 5 'post_type' => 'post', 6 'posts_per_page' => -1, 7 'post_status' => 'any', 8 'fields' => 'ids', 9 ) ); 10 foreach ( $posts as $post_id ) { 11 $cover = get_field( 'bookcover', $post_id ); 12 if ( $cover ) { 13 $all_good_pictures[] = $cover; 14 } 15 } 16 17 // List images (CPT 'book_list', field 'book_list_pictrue') 18 $lists = get_posts( array( 19 'post_type' => 'book_list', 20 'posts_per_page' => -1, 21 'post_status' => 'any', 22 'fields' => 'ids', 23 ) ); 24 foreach ( $lists as $list_id ) { 25 $pic = get_field( 'book_list_pictrue', $list_id ); 26 if ( $pic ) { 27 $all_good_pictures[] = $pic; 28 } 29 } 30 31 // Author photos (CPT 'bookauthor', field 'bookauthor_picture') 32 $authors = get_posts( array( 33 'post_type' => 'bookauthor', 34 'posts_per_page' => -1, 35 'post_status' => 'any', 36 'fields' => 'ids', 37 ) ); 38 foreach ( $authors as $author_id ) { 39 $pic = get_field( 'bookauthor_picture', $author_id ); 40 if ( $pic ) { 41 $all_good_pictures[] = $pic; 42 } 43 } 44 45 $all_good_pictures = array_filter( $all_good_pictures );
Reaalses projektis, raamatupoes, võimaldas see lähenemine välja arvutada suurema osa rämpsfailidest ja vabastada märkimisväärse osa kettaruumist.
5.2. Kustuta kõik, mis pole valges nimekirjas
Nüüd käi läbi wp-content/uploads ja kustuta iga fail, mida pole massiivis $all_good_pictures:
1 $uploads_dir = wp_upload_dir(); 2 $search = $uploads_dir['basedir']; 3 $replace = $uploads_dir['baseurl']; 4 $root = $uploads_dir['basedir']; 5 6 $iter = new RecursiveIteratorIterator( 7 new RecursiveDirectoryIterator( $root, RecursiveDirectoryIterator::SKIP_DOTS ), 8 RecursiveIteratorIterator::SELF_FIRST, 9 RecursiveIteratorIterator::CATCH_GET_CHILD 10 ); 11 12 foreach ( $iter as $fileinfo ) { 13 if ( $fileinfo->isFile() ) { 14 $image_path = $fileinfo->getPathname(); 15 $image_url = str_replace( $search, $replace, $image_path ); 16 17 if ( ! in_array( $image_url, $all_good_pictures, true ) ) { 18 unlink( $image_path ); 19 } 20 } 21 }
in_array() meetod range võrdlusega 10 000+ elemendiga massiivil pole kõige kiirem. Tootmismahtude jaoks asenda tavaline massiiv assotsiatiivsega: $all_good_pictures = array_fill_keys( $all_good_pictures, true ) ja kontrolli isset() abil. Erinevus 40 000 elemendi puhul, kümnetest sekunditest sekundi murdosadeni.
Kuidas neid funktsioone käivitada
Kõik ülaltoodud koodijupid on funktsioonide definitsioonid. Need ei tee midagi enne, kui neid välja kutsud. Kolm ohutut käivitamisviisi:
Meetod | Millal kasutada | Tagasipööramine |
|---|---|---|
WP-CLI | Ühekordne puhastus, konsooli ligipääs | Ei, ainult varukoopia |
Konks | Konsooli pole, vaja käivitada administ | Ei, ainult varukoopia |
Koodijupi plugin (WPCode) | Mugav salvestamine ja lubamine/keelamine | Keela koodijupp, funktsioon passiivne |
Näide ühekordsest käivitamisest admini kaudu:
1 add_action( 'admin_init', 'run_cleanup_once' ); 2 function run_cleanup_once() { 3 if ( isset( $_GET['cleanup'] ) && 'confirmed' === $_GET['cleanup'] ) { 4 delete_unattached_attachments(); 5 } 6 }
Külasta https://yoursite.com/wp-admin/?cleanup=confirmed, funktsioon käivitub ühe korra. Pärast käivitamist eemalda koodijupp.
WP-CLI jaoks, mis on tootmiskeskkonnas soovitatav meetod, salvesta funktsiooni kood ajutisse faili ja käivita:
1 wp eval-file cleanup.php
Enne puhastamist on kasulik protsessi visuaalselt näha. Allolevas videos on samm-sammuline ülevaade WordPressi meediumikogu puhastamisest käsitsi ja automaatsete meetoditega.
⁉️🤔 Korduma kippuvad küsimused
Kas faile saab pärast kustutamist taastada?
Ei. Funktsioonid kasutavad
wp_delete_attachment()parameetrigatruejaunlink(), failid kustutatakse füüsiliselt, prügikastist mööda minnes. Ainus kindlustus: täielik varukoopia failidest ja andmebaasist enne käivitamist. Kontrolli, kas sinu hostinguteenuse pakkujal on automaatsed igapäevased varukoopiad, Kinsta, WP Engine ja SiteGround puhul on need vaikimisi lubatud. See annab täiendava taastepunkti lisaks sinu käsitsi varukoopiale.
Miks funktsioon ei töötanud, failid jäid alles?
Kõige tavalisem põhjus: lisasid funktsiooni definitsiooni faili
functions.php, kuid ei kutsunud seda välja.function ... { }plokk on vaid juhis. Koodi käivitamiseks tuleb funktsioon siduda konksugaadd_action()kaudu või käivitada käsitsi WP-CLI kaudu. Jaotises „Kuidas käivitada" on kolm meetodit, vali vastavalt oma serveri ligipääsu tasemele.
Kas funktsioon kustutab kasutatavate piltide pisipildid, kui need on sidumata manused?
Ei. Pisipiltidel (thumbnail, medium, large) on sama
post_parentmis originaalmanusel. Funktsioon filtreerib rangelt tingimusegapost_parent = 0, ainult kirjed, millel pole üldse vanempostitust. Originaalide suurused pärivadpost_parentväärtuse ega satu valikusse. Probleem tekib ainult siis, kui originaal ise on oma seose kaotanud, siis kustutab funktsioon selle koos kõigi suurustega.
Mis siis, kui mõned pildid on kohandatud väljadel ja mõned on tavalised manused?
Kombineeri jaotiste 4 ja 5 lähenemisi. Esmalt kogu valge nimekiri kohandatud väljadest (jaotis 5.1). Seejärel üleslaadimiste skaneerimisel (jaotis 4) kontrolli iga faili puhul mõlemat tingimust: kas fail on WordPressi manus
attachment_url_to_postid()kaudu JA kas see on valges nimekirjas. Fail kustutatakse ainult siis, kui kumbki tingimus pole täidetud:if ( ! $attachment_id && ! isset( $good_pictures[ $image_url ] ) ) { unlink( $image_path ); }.
Kui turvaline see on WooCommerce'i saidi jaoks?
WooCommerce salvestab tootepildid standardsete WordPressi manustena, need on seotud postitüübiga
product. Sidumata manuste kustutamise funktsioon (jaotis 1) neid ei puuduta. Kuid funktsioon kindla CPT jaoks (jaotis 2), jah, kui sisestad'product'. WooCommerce'i jaoks on kõige turvalisem jaotise 5 meetod (valge nimekiri): see opereerib sellega, mida tegelikult kasutatakse, mitte sellega, mis on seotud. Enne käivitamist ekspordi kõigi tootemanuste ID-d ristkontrolliks.
Mida oma projektis kasutada: lõplik jaotus
Meetodi valik sõltub saidi arhitektuurist:
- Tavaline blogi või uudistesait, jaotiste 1 (sidumata manused) ja 3 (404 manused) funktsioonidest piisab. Käivita kord poole aasta jooksul, meediumikogu on korras.
- Sait vanade CPT-dega (portfoolio, kataloog, kuulutused), lisa jaotis 2. Puhasta täpselt rämps kustutatud või mahajäetud postitüüpidest.
- Projekt ACF/Meta Boxil kohandatud pildiväljadega, sinu valik: jaotis 5. Koosta valge nimekiri, kustuta ülejäänu. Seadista üks kord, seejärel lihtsalt korda vastavalt vajadusele.
- Kõik koos ja ebaselge, alusta üleslaadimiste rekursiivsest skaneerimisest (jaotis 4). Vaata, kui palju rämpsu kettal istub. Seejärel rakenda jaotisi 1-3 ja 5 valikuliselt vastavalt olukorrale.
Ükski neist skriptidest ei asenda regulaarset saidihügieeni. Kuid kui kirjutad vajaliku funktsiooni ja salvestad selle projektidokumentatsiooni, säästad järgmisel auditil tunde käsitsitööd.
Ja jah, sa juba tegid varukoopia.




