Trūkstošo izcelto attēlu masveida piešķiršana WordPress

No comments

05.09.2026|

No comments

Tiempo de lectura Lectura: 13 min, 22 s
Número de palabras Palabras: 2473
Número de visitas Visitas: 22
Icono de traducción
WordPress vidē vienlaikus pievienot trūkstošos izcelto attēlu. Saraksts, kurā redzami gan trūkstošie, gan esošie attēli.

Pirms dažām dienām es pabeidzu sen jau jāizdarītu uzdevumu, ko biju atlikusi jau ļoti ilgu laiku. Esatguvu visustrūkstošos izcelto attēlu attēlus un pievienoju visiem attēliem trūkstošo alternatīvo tekstu. Es arī pabeidzu rakstīt visus trūkstošos metadeskriptīvos tekstus. Kopumā es pievienoju vai rediģēju vairāk nekā 15 000 ierakstus, izmantojot trīs savus vienreizējus skriptus. Šodien es šeit dalos ar skriptu, kas ļauj atgūt trūkstošos izcelto attēlu attēlus, kuru es izmantoju arī, lai veiktu šo uzdevumu citās vietnēs.

Ja jau kādu laiku rakstāt blogu, ir diezgan iespējams, ka jums ir diezgan daudz vecāku ierakstu, kuriem nav pievienota izcelta attēla. Tas bieži notika klasiskā redaktora laikos, kad attēlu ievietojām tieši ieraksta tekstā, bet aizmirsām to atzīmēt laukā „Galvenais attēls”.

Rakstu publicēšana bez izcelta attēla nav tikai estētiska problēma; tā tieši ietekmē jūsu vietnes optimizāciju un lietotāju pieredzi:

  1. Sociālais SEO un Open Graph: daloties ar ierakstu sociālajos tīklos, ziņapmaiņas lietotnēs vai satura agregatoros, Open Graph birkas (og:image) nespēj atrast skaidri identificējamu resursu, ko parādīt, tādējādi ievērojami samazinot CTR (klikšķu rādītāju).
  2. Tēmas vizuālā vienotība: mūsdienu veidnes (piemēram, tās, kas izstrādātas, izmantojot GeneratePress vai GenerateBlocks) izmanto izcelto attēlu, lai veidotu arhīva režģus, saistīto ierakstu sarakstus vai galvenes. Bez tā izkārtojums sabojājas vai paliek nepareizi izvietotas atstarpes.
  3. Atklāšana un plūsmas (RSS / Google Discover): Tādi rīki kā „Google Discover“ vai RSS lasītāji dod priekšroku vai prasa, lai saturam būtu pievienota augstas izšķirtspējas sīktēla attēls, lai uzlabotu raksta karti.

Lai atrisinātu šo problēmu, neizmantojot spraudņus (piemēram, šo) vai lēnus procesus, esmu izveidojis šo vienkāršo, vieglo PHP koda fragmentu, kas automātiski katra ieraksta pirmo attēlu iestata kā izcelto attēlu tieši no WordPress vadības paneļa. Ja jūsu ierakstam nav neviena attēla, varat piešķirt noklusējuma attēlu, pievienojot tā URL koda fragmentam.

Ko tieši dara šis koda fragments?

Šis kods pievieno viedu, iebūvētu partiju apstrādes rīku WordPress ierakstu sarakstam (wp-admin/edit.php):

  • Pievienojiet pielāgotu sleju: izveidojiet sleju „Trūkst izcelta attēla” ierakstu sarakstā, lai uzreiz redzētu, kuriem ierakstiem trūkst sīktēla.
  • 3 posmu apstrāde: Kad aktivizējat attēla piešķiršanu ierakstam, attēls tiek meklēts tieši šādā secībā:
    1. Pārbaudiet, vai mediju bibliotēkā ir kādi attēli, kas pievienoti tieši šim ierakstam.
    2. Ja nav tiešu pielikumu (piemēram, ja tie tika ievietoti, izmantojot attēla bloku vai HTML), pārskatiet saturu, meklējot pirmo <img> tagu, lai izvilktu tā ID, izmantojot funkciju attachment_url_to_postid().
    3. Ja ierakstā nav neviena attēla, tiek piešķirts konfigurācijā norādītais noklusējuma (rezerves) attēls.
  • AJAX masveida apstrāde (partiju apstrāde): Virsrakstā ir iekļauta poga („⚡ Piešķirt visus šajā lapā”), kas secīgi apstrādā visus ekrānā redzamos ierakstus, izmantojot secīgus asinhronos pieprasījumus. To var izdarīt arī manuāli, izmantojot atsevišķu pogu katram saraksta ierakstam.
  • Filtrēt nepublicētos ierakstus: automātiski izslēdz ierakstus, kas atrodas nepublicētajā statusā, lai jūs varētu koncentrēties vienīgi uz publicēto saturu.
  • Šķirojama kolonna: ļauj šķirot sarakstu tā, lai visi ieraksti bez izcelta attēla tiktu apkopoti kopā saraksta augšgalā.

Kāpēc tas ir tik viegls un vai tas neietekmē servera veiktspēju?

Bieži sastopama baža, izmantojot šāda veida automatizētus rīkus, ir bailes no datu bāzes bloķēšanās vai PHP atmiņas pārslodzes vietnēs, kurās ir tūkstošiem rakstu. Šis kods ir izstrādāts, ievērojot šādus optimizācijas kritērijus:

1. Tas darbojas tikai sadaļā „Admin” (is_admin())

Kods ir paredzēts izmantošanai vienīgi administrācijas paneļa ievades ekrānā (edit.php). Tas nepievieno nevienu lieku rindu pieprasījumiem publiskajā vietnē. Tas nekādā veidā neietekmēs jūsu lietotājus un ātruma rādītājus.

2. Nosūtiet pieprasījumus uz Meta Cache

Lai noteiktu, vai ierakstā ir attēls, šis kods neveic sarežģītas datu bāzes meklēšanas katrai rindai atsevišķi. Tas izmanto metadatu atslēgu _thumbnail_id, kuru WordPress, renderējot sarakstu, ielādē atmiņā tieši caur metadatu kešatmiņu. Tabula ielādējas gandrīz uzreiz.

3. Kaskādes veida asinhronā apstrāde (sekvenciāla AJAX cilpa)

Tā vietā, lai veiktu apjomīgu vaicājumu datu bāzē, lai vienā reizē atjauninātu 700 vai 1 000 ierakstus (kas izraisītu laika limitu pārsniegšanu vai iztērētu visu servera atmiņu), poga „Piešķirt visus” apstrādā ierakstus vienu pēc otra, izmantojot JavaScript solījumus:

POST 1 (AJAX)⟶Atbilde „OK“⟶POST 2 (AJAX)⟶Atbilde „OK“…

Tas nodrošina stabilu un konsekventu resursu izmantošanu, ļaujot jums reāllaikā sekot līdzi progresam, rindu pa rindai.

4. Nav failu dublikātu

Šis skripts nelejupielādē, neapvieno un nedublē attēlus jūsu cietajā diskā. Tas vienkārši ņem attēla identifikatoru, kas jau atrodas jūsu multivides bibliotēkā, un saista to ar ierakstu, piešķirot atbilstošo meta_value vērtību tabulā wp_postmeta.

Kods (PHP + JavaScript)

Šo kodu varat pievienot savas apakštēmas failam „functions.php“, pielāgotam spraudnim vai izmantot kādu pielāgotu funkciju spraudni, piemēram, „Code Snippets“ vai tamlīdzīgu.

Piezīme: Neaizmirstiet 56. rindā mainīt mainīgā $default_image_url vērtību uz pilnu URL adresi, kas attēlo vispārējo attēlu, kuru vēlaties piešķirt ierakstiem, kuru tekstā nav neviena attēla.

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
}

Kā to lietot?

  • Atveriet sarakstu „Ieraksti” savā administratora panelī.
  • Atveriet augšpusē esošo cilni „Rādīšanas opcijas” un mainiet vienā lapā rādāmo ierakstu skaitu uz 50 vai 100. (Sāciet ar mazākiem skaitļiem un pakāpeniski tos palieliniet, ja serveris reaģē labi.)

Trūkstošo izcelto attēlu masveida piešķiršana WordPress. Rādīšanas opcijas

  • Noklikšķiniet uz kolonnas virsraksta „Trūkstošie izceltie ieraksti”, lai šķirotu un grupētu neizpildītos ierakstus. Filtros varat izvēlēties starp „Ir”, „Trūkst” vai „Visi”
  • Kad esat pārliecināts, ka esat gatavs sākt trūkstošo izcelto attēlu piešķiršanu partijās, noklikšķiniet uz zilās pogas ar uzrakstu „Assign all on this page” un ļaujiet kaskādes procesam pabeigt sīktēlu piešķiršanu šai partijai. Ja vēlaties, varat tos piešķirt pa vienam.
  • Pārejiet uz nākamo lapu un atkārtojiet šo darbību, līdz būsiet pabeiguši bibliotēkas sakārtošanu.

Pēc izvēles: automātiskās piešķiršanas kods

Lai turpmāk šo darbību nevajadzētu atkārtot, varat pievienot šo īso koda fragmentu. Tas darbojas fonā tikai tad, kad saglabājat vai publicējat ierakstu: ja tas konstatē, ka neesat manuāli izvēlējies izcelto attēlu, tas automātiski piešķir pirmo attēlu saturā (vai noklusējuma rezerves attēlu, kuru jums būs jāpievieno $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 );
        }
    }
}

Komentēt

Vai ir kaut kas sakāms?

Este blog se aloja en LucusHost

LucusHost, el mejor hosting