Assegnazione in blocco delle immagini in evidenza mancanti in WordPress

No comments

05.09.2026|

No comments

Tiempo de lectura Lectura: 12 min, 41 s
Número de palabras Palabras: 2348
Número de visitas Visitas: 11
Icono de traducción
Assegnare in blocco le immagini in evidenza mancanti in WordPress. Un elenco che mostra sia quelle mancanti che quelle esistenti.

Qualche giorno fa ho portato a termine un compito che avrei dovuto svolgere già da tempo, ma che avevo rimandato per un’eternità.Ho recuperato tuttele immagini in evidenza mancanti e ho aggiunto il testo alternativo mancante a tutte le immagini. Ho anche finito di scrivere tutte le meta descrizioni mancanti. In totale, ho aggiunto o modificato oltre 15.000 record utilizzando tre dei miei snippet personalizzati. Oggi condivido qui lo snippet per recuperare le immagini in evidenza mancanti, che ho utilizzato anche per svolgere questo compito su altri siti.

Se scrivi sul blog da un po’ di tempo, è molto probabile che tu abbia diversi post più vecchi a cui non è stata assegnata un’immagine in evidenza. Questo succedeva spesso ai tempi dell’editor classico, quando inserivamo l’immagine direttamente nel corpo del post ma ci dimenticavamo di selezionarla nella casella “Immagine in evidenza”.

Pubblicare articoli senza un’immagine in evidenza non è solo una questione estetica, tra le altre cose; influisce direttamente sull’ottimizzazione del tuo sito e sull’esperienza dell’utente:

  1. Social SEO e Open Graph: quando si condivide un post sui social media, sulle app di messaggistica o sugli aggregatori di contenuti, i tag Open Graph (og:image) non riescono a individuare una risorsa chiara da visualizzare, riducendo drasticamente il CTR (tasso di clic).
  2. Coerenza visiva nel tema: i modelli moderni (come quelli realizzati con GeneratePress o GenerateBlocks) si basano sull’immagine in evidenza per creare griglie di archiviazione, elenchi di post correlati o intestazioni. Senza di essa, il layout risulta compromesso o presenta spazi disallineati.
  3. Scoperta e feed (RSS / Google Discover): strumenti come Google Discover o i lettori RSS danno priorità o richiedono contenuti corredati da una miniatura ad alta risoluzione per migliorare la scheda dell'articolo.

Per risolvere il problema senza ricorrere a plugin (come questo) o a processi lenti, ho creato questo snippet PHP semplice e leggero che imposta automaticamente la prima immagine di ogni post come immagine in evidenza, direttamente dalla dashboard di WordPress. Se il tuo post non contiene immagini, puoi assegnarne una predefinita aggiungendo il relativo URL al codice.

Cosa fa esattamente questo frammento di codice?

Il codice aggiunge uno strumento di elaborazione in batch integrato e intuitivo all'elenco dei post di WordPress (wp-admin/edit.php):

  • Aggiungi una colonna personalizzata: crea la colonna “Immaginein evidenza mancante nell’elenco dei post per vedere a colpo d’occhio quali post non hanno una miniatura.
  • Elaborazione a 3 livelli: quando si attiva l'assegnazione per un post, l'immagine viene cercata esattamente in questo ordine:
    1. Verifica se nella Libreria multimediale sono presenti immagini allegate direttamente al post.
    2. Se non sono presenti allegati diretti (ad esempio, se sono stati inseriti tramite un blocco immagine o codice HTML), cercare nel contenuto il primo tag <img> per estrarne l'ID utilizzando la funzione attachment_url_to_postid().
    3. Se la voce non contiene assolutamente nessuna immagine, viene assegnata un'immagine predefinita (di riserva) specificata nella configurazione.
  • Elaborazione in blocco con AJAX (elaborazione a lotti): include un pulsante nell'intestazione (“⚡ Assegna tutto in questa pagina”) che elabora in sequenza tutte le voci visibili sullo schermo tramite richieste asincrone consecutive. È possibile eseguire questa operazione anche manualmente utilizzando il pulsante individuale presente per ogni post nell'elenco.
  • Filtra le bozze: esclude automaticamente le voci con stato “bozza”, consentendoti di concentrarti esclusivamente sui contenuti pubblicati.
  • Colonna ordinabile: consente di ordinare l'elenco in modo che tutte le voci prive di immagine in evidenza vengano raggruppate insieme nella parte superiore.

Perché è così leggero e non influisce sulle prestazioni del server?

Una preoccupazione comune quando si utilizza questo tipo di strumento automatizzato è il timore che il database si blocchi o che la memoria PHP venga sovraccaricata su siti con migliaia di articoli. Questo snippet è stato progettato in linea con i seguenti criteri di ottimizzazione:

1. Funziona solo nella sezione Amministrazione (is_admin())

Il codice è ottimizzato esclusivamente per la schermata di inserimento dati del pannello di amministrazione (edit.php). Non aggiunge alcuna linea di codice superflua alle richieste sul sito pubblico. Gli utenti e le metriche relative alla velocità non ne risentiranno in alcun modo.

2. Indirizzare le richieste alla cache Meta

Per stabilire se un post contenga o meno un'immagine, lo snippet non esegue ricerche complesse nel database per ogni riga. Utilizza infatti la chiave di metadati _thumbnail_id, che WordPress carica in memoria in modo nativo tramite la cache dei metadati durante il rendering dell'elenco. La tabella viene caricata quasi istantaneamente.

3. Elaborazione asincrona a cascata (ciclo AJAX sequenziale)

Anziché eseguire una query di grandi dimensioni sul database per aggiornare 700 o 1.000 voci in una sola volta (il che causerebbe un timeout o esaurirebbe tutta la memoria del server), il pulsante “Assegna tutto” elabora le voci una per una utilizzando le promesse JavaScript:

POST 1 (AJAX)⟶Risposta OK⟶POST 2 (AJAX)⟶Risposta OK…

Ciò garantisce un utilizzo stabile e coerente delle risorse, consentendoti di vedere i progressi in tempo reale, riga per riga.

4. Nessuna duplicazione dei file

Lo snippet non scarica, non ricompone né duplica le immagini sul tuo disco rigido. Si limita a prelevare l’ID dell’immagine già presente nella tua Libreria multimediale e a collegarla al post assegnandole il meta_value corrispondente nella tabella wp_postmeta.

Il codice (PHP + JavaScript)

Puoi aggiungere questo codice al file functions.php del tuo tema figlio, a un plugin personalizzato oppure tramite un plugin di funzioni personalizzate come Code Snippets o simili.

Nota: ricordati di impostare la variabile $default_image_url alla riga 56 con l'URL completo dell'immagine generica che desideri assegnare ai post che non contengono immagini nel testo.

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
}

Come si usa?

  • Vai all'elenco "Post" nel tuo pannello di amministrazione.
  • Apri la scheda "Opzioni di visualizzazione" in alto e imposta il numero di elementi da visualizzare su 50 o 100 per pagina. (Inizia provando con numeri più bassi e aumentali gradualmente se il server risponde bene.)

Assegnazione in blocco delle immagini in evidenza mancanti in WordPress. Opzioni di visualizzazione

  • Clicca sull'intestazione della colonna "Evidenziazioni mancanti" per ordinare e raggruppare le voci in sospeso. Nei filtri puoi scegliere tra "Presenti", "Mancanti" o "Tutte"
  • Una volta che sei sicuro di essere pronto per iniziare ad assegnare in blocco le immagini in evidenza mancanti, clicca sul pulsante blu con l’etichetta “Assegna tutte in questa pagina” e lascia che il processo a cascata completi l’assegnazione delle miniature per quel blocco. Se preferisci, puoi assegnarle una per una.
  • Passa alla pagina successiva e ripeti l'operazione finché non avrai finito di riordinare la tua libreria.

Opzionale: snippet per l'assegnazione automatica

Per evitare di dover ripetere questa operazione in futuro, puoi aggiungere questo breve frammento di codice. Viene eseguito in background solo quando salvi o pubblichi un post: se rileva che non hai selezionato manualmente un’immagine in evidenza, assegna automaticamente la prima immagine presente nel contenuto (o l’immagine predefinita, che dovrai aggiungere in $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 );
        }
    }
}

Lascia un commento

Qualcosa da dire?

Este blog se aloja en LucusHost

LucusHost, el mejor hosting