
Pred pár dňami som dokončil úlohu, ktorá už dávno mala byť hotová, ale odkladal som ju už veľmi dlho.Doplnil som všetkychýbajúce hlavné obrázky a pridal som k obrázkom všetky chýbajúce alternatívne texty. Takisto som dokončil písanie všetkých chýbajúcich meta popisov. Celkovo som pomocou troch vlastných jednorazových skriptov pridal alebo upravil viac ako 15 000 záznamov. Dnes tu zdieľam skript na obnovenie chýbajúcich hlavných obrázkov, ktorý som použil aj na vykonanie tejto úlohy na iných stránkach.
Ak už nejakú dobu blogujete, je dosť pravdepodobné, že máte pomerne veľa starších príspevkov, ku ktorým nie je priradený žiadny hlavný obrázok. K tomu dochádzalo často v časoch klasického editora, keď sme obrázok vkladali priamo do textu príspevku, ale zabudli sme ho vybrať v poli „Hlavný obrázok“.
Zverejňovanie príspevkov bez hlavného obrázku nie je len estetickým problémom, ale okrem iného priamo ovplyvňuje optimalizáciu vašej stránky a používateľský zážitok:
- Sociálne SEO a Open Graph: Pri zdieľaní príspevku na sociálnych sieťach, v aplikáciách na zasielanie správ alebo na agregátoroch obsahu nemôžu tagy Open Graph (
og:image) nájsť jasný zdroj, ktorý by sa mal zobraziť, čo výrazne znižuje CTR (miera preklikov). - Vizuálna jednotnosť šablóny: Moderné šablóny (napríklad tie, ktoré boli navrhnuté pomocou GeneratePress alebo GenerateBlocks) využívajú hlavný obrázok na vytvorenie mriežok archívu, zoznamov súvisiacich príspevkov alebo hlavičiek. Bez neho sa rozloženie naruší alebo vzniknú nesprávne zarovnané medzery.
- Objavovanie a kanály (RSS / Google Discover): Nástroje ako Google Discover alebo čítačky RSS uprednostňujú alebo vyžadujú obsah s priloženou miniatúrou vo vysokom rozlíšení, aby sa vylepšila vizuálna prezentácia článku.
Aby som tento problém vyriešil bez použitia doplnkov (ako je napríklad tento) alebo pomalých procesov, vytvoril som tento jednoduchý a nenáročný úryvok kódu v PHP, ktorý automaticky nastaví prvý obrázok v každom príspevku ako hlavný obrázok, a to priamo z riadiaceho panela WordPressu. Ak váš príspevok neobsahuje žiadne obrázky, môžete mu priradiť predvolený obrázok pridaním jeho URL adresy do kódu.
Čo presne tento úrytok kódu robí?
Tento kód pridáva do zoznamu príspevkov v systéme WordPress (wp-admin/edit.php) inteligentný integrovaný nástroj na hromadné spracovanie:
- Pridať vlastný stĺpec: Vytvorte v zozname príspevkov stĺpec „Chýbajúci hlavný obrázok“, aby ste na prvý pohľad videli, ktorým príspevkom chýba náhľad.
- 3-fázové spracovanie: Keď aktivujete priradenie k príspevku, systém vyhľadáva obrázok presne v tomto poradí:
- Skontrolujte, či sú v mediálnej knižnici priamo k príspevku pripojené nejaké obrázky.
- Ak neexistujú žiadne priame prílohy (napríklad ak boli vložené prostredníctvom obrazového bloku alebo kódu HTML), prehľadajte obsah a vyhľadajte prvú značku
<img>, aby ste pomocoufunkcie attachment_url_to_postid()získali jej ID. - Ak záznam neobsahuje absolútne žiadne obrázky, priradí sa mu predvolený (náhradný) obrázok uvedený v konfigurácii.
- Hromadné spracovanie pomocou AJAX (dávkové spracovanie): V záhlaví sa nachádza tlačidlo („⚡ Priradiť všetko na tejto stránke“), ktoré postupne spracováva všetky záznamy viditeľné na obrazovke prostredníctvom po sebe idúcich asynchrónnych požiadaviek. Túto operáciu môžete vykonať aj ručne pomocou samostatného tlačidla pri každom príspevku v zozname.
- Filtrovanie náčrtov: Automaticky vylučuje záznamy so stavom „náčrt“, aby ste sa mohli sústrediť výlučne na publikovaný obsah.
- Stĺpec, podľa ktorého je možné triediť: Umožňuje zoradiť zoznam tak, aby sa všetky záznamy bez hlavného obrázka zoskupili spolu na začiatku zoznamu.
Prečo je to také ľahké a neovplyvňuje to výkon servera?
Bežnou obavou pri používaní tohto typu automatizovaného nástroja je strach z zablokovania databázy alebo preťaženia pamäte PHP na stránkach s tisíckami článkov. Tento úryvok kódu bol navrhnutý v súlade s nasledujúcimi kritériami optimalizácie:
1. Funguje iba v sekcii pre správcov (is_admin())
Kód je určený výlučne pre obrazovku zadávania údajov v administračnom paneli (edit.php). Nepridáva ani jediný riadok kódovej záťaže k požiadavkám na verejnej stránke. Vaši používatelia ani ukazovatele rýchlosti nebudú nijako ovplyvnení.
2. Smerujte dotazy do meta-cache
Na zistenie, či príspevok obsahuje obrázok, tento úryvok kódu nevykonáva zložité vyhľadávanie v databáze pre každý riadok. Využíva kľúč metadát _thumbnail_id, ktorý WordPress pri vykresľovaní zoznamu načíta priamo do pamäte prostredníctvom vyrovnávacej pamäte metadát. Tabuľka sa načíta takmer okamžite.
3. Kaskádové asynchrónne spracovanie (sekvenčná AJAX slučka)
Namiesto toho, aby sa v databáze spustil rozsiahly dotaz na aktualizáciu 700 alebo 1 000 záznamov naraz (čo by viedlo k vypršaniu časového limitu alebo k vyčerpaniu celej pamäte servera), tlačidlo „Priradiť všetko“ spracováva záznamy jeden po druhom pomocou sľubov v jazyku JavaScript:
POST 1 (AJAX)⟶odpoveď OK⟶POST 2 (AJAX)⟶odpoveď OK…
Tým sa zabezpečuje stabilné a konzistentné využívanie zdrojov, vďaka čomu môžete sledovať pokrok v reálnom čase, riadok po riadku.
4. Žiadne duplicitné súbory
Tento skript nestahuje, neslučuje ani neduplikuje obrázky na vašom pevnom disku. Jednoducho preberie identifikátor obrázku, ktorý sa už nachádza vo vašej mediálnej knižnici, a prepojí ho s príspevkom tak, že mu v tabuľke wp_postmeta priradí príslušnú hodnotu meta_value.
Kód (PHP + JavaScript)
Tento kód môžete pridať do súboru functions.php vašej podtémy, do vlastného pluginu alebo prostredníctvom pluginu s vlastnými funkciami, ako je napríklad Code Snippets alebo podobný.
Poznámka: Nezabudnite v riadku 56 nastaviť premennú
$default_image_urlna úplnú URL adresu všeobecného obrázku, ktorý chcete priradiť k príspevkom, ktorých text neobsahuje žiadne obrázky.
PHP
// 1. Añadir columna personalizada en el listado de entradas
add_filter( 'manage_posts_columns', 'custom_featured_status_column' );
function custom_featured_status_column( $columns )
$columns['featured_missing'] = 'Destacada Faltante';
return $columns;
}
// 2. Hacer la columna ordenable al hacer clic en el encabezado
add_filter( 'manage_edit-post_sortable_columns', 'custom_featured_sortable_column' );
function custom_featured_sortable_column( $columns ) {
$columns['featured_missing'] = 'featured_missing';
return $columns;
}
// 3. Modificar la consulta para ordenar por presencia de _thumbnail_id
add_action( 'pre_get_posts', 'custom_featured_column_orderby' );
function custom_featured_column_orderby( $query ) {
if ( ! is_admin() || ! $query->is_main_query() ) return;
if ( $query->get( 'orderby' ) === 'featured_missing' ) {
$query->set( 'meta_key', '_thumbnail_id' );
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_compare', 'NOT EXISTS' );
}
}
// 3.1. Añadir desplegable de filtro nativo en el listado de entradas
add_action( 'restrict_manage_posts', 'custom_featured_filter_dropdown' );
function custom_featured_filter_dropdown( $post_type ) {
if ( $post_type !== 'post' ) return;
$selected = isset( $_GET['filter_featured_status'] ) ? sanitize_text_field( $_GET['filter_featured_status'] ) : '';
?>
<select name="filter_featured_status" id="filter_featured_status">
<option value=""><?php _e( 'Todas las destacadas', 'textdomain' ); ?></option>
<option value="has_img" <?php selected( $selected, 'has_img' ); ?>>Tiene</option>
<option value="missing_img" <?php selected( $selected, 'missing_img' ); ?>>Falta</option>
</select>
<?php
}
// 3.2. Aplicar el filtro del desplegable a la consulta de WP_Query
add_filter( 'parse_query', 'custom_featured_filter_apply' );
function custom_featured_filter_apply( $query ) {
global $pagenow;
if ( ! is_admin() || $pagenow !== 'edit.php' || ! $query->is_main_query() ) return;
if ( isset( $_GET['filter_featured_status'] ) && $_GET['filter_featured_status'] !== '' ) {
$filter_value = sanitize_text_field( $_GET['filter_featured_status'] );
$meta_query = (array) $query->get( 'meta_query' );
if ( $filter_value === 'has_img' ) {
$meta_query[] = array(
'key' => '_thumbnail_id',
'compare' => 'EXISTS',
);
} elseif ( $filter_value === 'missing_img' ) {
$meta_query[] = array(
'key' => '_thumbnail_id',
'compare' => 'NOT EXISTS',
);
}
$query->set( 'meta_query', $meta_query );
}
}
// 4. Mostrar el estado y el botón rápido en la columna (Excluyendo borradores)
add_action( 'manage_posts_custom_column', 'custom_featured_status_column_content', 10, 2 );
function custom_featured_status_column_content( $column, $post_id ) {
if ( $column === 'featured_missing' ) {
if ( get_post_type( $post_id ) !== 'post' || get_post_status( $post_id ) === 'draft' ) {
echo '<span style="color: #999;">—</span>';
return;
}
$has_thumbnail = get_post_meta( $post_id, '_thumbnail_id', true );
if ( $has_thumbnail ) {
echo '<span style="color: #46b450; font-weight: bold;">✔ Tiene</span>';
} else {
echo '<span style="color: #dc3232; font-weight: bold;">❌ Falta</span> ';
echo '<button type="button" class="button button-small set-first-img-btn" data-postid="' . esc_attr( $post_id ) . '">Asignar imagen</button>';
echo '<span class="set-img-status" style="margin-left:5px;"></span>';
}
}
}
// 5. Procesar la asignación por AJAX (con fallback a la imagen por defecto)
add_action( 'wp_ajax_set_first_image_as_featured', 'ajax_set_first_image_as_featured' );
function ajax_set_first_image_as_featured() {
check_ajax_referer( 'set_first_image_nonce', 'nonce' );
$post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;
if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
wp_send_json_error( 'Sin permisos o ID inválido' );
}
if ( get_post_status( $post_id ) === 'draft' ) {
wp_send_json_error( 'La entrada es un borrador' );
}
// =========================================================================
// CONFIGURACIÓN: Reemplaza esta URL por la URL completa de tu imagen por defecto
// =========================================================================
$default_image_url = 'https://tu-dominio.com/wp-content/uploads/imagen-por-defecto.jpg';
// A. Buscar adjuntos directos al post
$attachments = get_posts( array(
'post_type' => 'attachment',
'posts_per_page' => 1,
'post_parent' => $post_id,
'post_mime_type' => 'image',
'orderby' => 'menu_order',
'order' => 'ASC',
'fields' => 'ids'
) );
if ( ! empty( $attachments ) ) {
set_post_thumbnail( $post_id, $attachments[0] );
wp_send_json_success( '¡Asignada primera!' );
}
// B. Si no hay adjuntos, buscar <img> en el contenido
$post = get_post( $post_id );
preg_match_all( '/<img.+?src=[\'"]([^\'"]+)[\'"]/i', $post->post_content, $matches );
if ( isset( $matches[1][0] ) ) {
$attachment_id = attachment_url_to_postid( $matches[1][0] );
if ( $attachment_id ) {
set_post_thumbnail( $post_id, $attachment_id );
wp_send_json_success( '¡Asignada primera!' );
}
}
// C. Si no hay ninguna imagen en el post, asignar la imagen por defecto
if ( ! empty( $default_image_url ) ) {
$default_id = attachment_url_to_postid( $default_image_url );
if ( $default_id ) {
set_post_thumbnail( $post_id, $default_id );
wp_send_json_success( '¡Asignada por defecto!' );
}
}
wp_send_json_error( 'No se encontró ninguna imagen en el post ni ID de fallback' );
}
// 6. Cargar JS y botón masivo en el admin (edit.php)
add_action( 'admin_footer-edit.php', 'custom_featured_ajax_script' );
function custom_featured_ajax_script() {
$screen = get_current_screen();
if ( $screen->post_type !== 'post' ) return;
$nonce = wp_create_nonce( 'set_first_image_nonce' );
?>
<script>
jQuery(document).ready(function($) {
$('<button type="button" id="process-all-page-btn" class="page-title-action" style="margin-left:10px; background:#2271b1; color:#fff; border-color:#2271b1;">⚡ Asignar todas en esta página</button>')
.insertAfter('.wp-heading-inline');
function processButton($btn) {
return new Promise(function(resolve) {
var $status = $btn.siblings('.set-img-status');
var postId = $btn.data('postid');
$btn.prop('disabled', true).text('Procesando...');
$.post(ajaxurl, {
action: 'set_first_image_as_featured',
post_id: postId,
nonce: '<?php echo $nonce; ?>'
}, function(response) {
if (response.success) {
$btn.parent().html('<span style="color: #46b450; font-weight: bold;">✔ ' + response.data + '</span>');
} else {
$status.css('color', '#dc3232').text(response.data);
$btn.prop('disabled', false).text('Asignar imagen');
}
resolve();
}).fail(function() {
$btn.prop('disabled', false).text('Error');
resolve();
});
});
}
$(document).on('click', '.set-first-img-btn', function(e) {
e.preventDefault();
processButton($(this));
});
$('#process-all-page-btn').on('click', async function(e) {
e.preventDefault();
var $batchBtn = $(this);
var $pendingButtons = $('.set-first-img-btn:not(:disabled)');
if ($pendingButtons.length === 0) {
alert('No hay entradas pendientes de asignar en esta página.');
return;
}
$batchBtn.prop('disabled', true).text('Procesando por lote...');
for (var i = 0; i < $pendingButtons.length; i++) {
await processButton($($pendingButtons[i]));
}
$batchBtn.text('¡Lote completado!').css('background', '#46b450');
setTimeout(function() {
$batchBtn.prop('disabled', false).text('⚡ Asignar todas en esta página').css('background', '#2271b1');
}, 3000);
});
});
</script>
<?php
}
Ako sa to používa?
- Prejdite do zoznamu „Príspevky“ vo vašom administrátorskom paneli.
- V hornej časti otvorte kartu „Možnosti zobrazenia“ a nastavte počet položiek na jednej stránke na 50 alebo 100. (Začnite s nižším počtom a postupne ho zvyšujte, ak server reaguje bez problémov.)

- Kliknutím na záhlavie stĺpca „Chýbajúce zvýraznenia“ môžete nezavedené položky zoradiť a zoskupiť. Vo filtroch si môžete vybrať medzi možnosťami „Obsahuje“, „Chýba“ alebo „Všetko“
- Akonáhle budete mať istotu, že ste pripravení začať hromadne priraďovať chýbajúce hlavné obrázky, kliknite na modré tlačidlo „ “ s nápisom „Priradiť všetko na tejto stránke“ a nechajte, aby kaskádový proces dokončil priraďovanie náhľadov pre danú dávku. Ak chcete, môžete ich priraďovať aj po jednom.
- Prejdite na ďalšiu stránku a postup opakujte, kým nedokončíte upratovanie svojej knižnice.
Voliteľné: úryvok k automatickému priradeniu
Aby ste túto úlohu v budúcnosti nemuseli opakovať, môžete pridať tento krátky kód. Spúšťa sa na pozadí len vtedy, keď uložíte alebo zverejníte príspevok: ak zistí, že ste ručne nevybrali hlavný obrázok, automaticky priradí prvý obrázok v obsahu (alebo predvolený náhradný obrázok, ktorý budete musieť pridať do $default_image_url =).
PHP
// Asignar imagen destacada automáticamente al publicar/guardar nuevas entradas
add_action( 'save_post_post', 'auto_set_featured_image_on_save', 10, 3 );
function auto_set_featured_image_on_save( $post_id, $post, $update ) {
// Evitar autoguardados, revisiones o peticiones AJAX/REST innecesarias
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( wp_is_post_revision( $post_id ) || $post->post_status === 'auto-draft' ) return;
// Si la entrada ya tiene imagen destacada marcada, no hacemos nada
if ( has_post_thumbnail( $post_id ) ) return;
$default_image_url = 'https://tu-dominio.com/wp-content/uploads/imagen-por-defecto.jpg';
// 1. Buscar primera imagen en el contenido
preg_match_all( '/<img.+?src=[\'"]([^\'"]+)[\'"]/i', $post->post_content, $matches );
if ( isset( $matches[1][0] ) ) {
$attachment_id = attachment_url_to_postid( $matches[1][0] );
if ( $attachment_id ) {
set_post_thumbnail( $post_id, $attachment_id );
return;
}
}
// 2. Si el post no tiene imágenes, asignar la imagen por defecto
if ( ! empty( $default_image_url ) ) {
$default_id = attachment_url_to_postid( $default_image_url );
if ( $default_id ) {
set_post_thumbnail( $post_id, $default_id );
}
}
}






