Menetapkan gambar unggulan yang belum ada secara massal di WordPress

No comments

05.09.2026|

No comments

Tiempo de lectura Lectura: 12 min, 21 s
Número de palabras Palabras: 2287
Número de visitas Visitas: 22
Icono de traducción
Menetapkan gambar unggulan yang hilang secara massal di WordPress. Daftar yang menampilkan gambar yang hilang maupun yang sudah ada.

Beberapa hari yang lalu, saya menyelesaikan sebuah tugas yang sudah lama tertunda dan memang harus diselesaikan, tetapi saya terus menundanya selama bertahun-tahun. Sayamengumpulkan semuagambar unggulan yang hilang dan menambahkan teks alternatif yang hilang ke semua gambar tersebut. Saya juga menyelesaikan penulisan semua deskripsi meta yang hilang. Secara total, saya menambahkan atau mengedit lebih dari 15.000 entri menggunakan tiga snippet buatan saya sendiri yang hanya digunakan sekali. Hari ini, saya membagikan snippet untuk mengambil gambar unggulan yang hilang di sini, yang juga saya gunakan untuk menyelesaikan tugas ini di situs-situs lain.

Jika Anda sudah cukup lama menulis blog, kemungkinan besar Anda memiliki cukup banyak postingan lama yang belum diberi gambar unggulan. Hal ini sering terjadi pada masa-masa penggunaan editor klasik, ketika kita menyisipkan gambar langsung ke dalam isi postingan tetapi lupa memilihnya di kotak ‘Gambar Unggulan’.

Mempublikasikan postingan tanpa gambar unggulan bukan sekadar masalah estetika, di antara hal-hal lainnya; hal ini secara langsung memengaruhi optimasi situs Anda dan pengalaman pengguna:

  1. SEO Media Sosial dan Open Graph: Saat membagikan postingan di media sosial, aplikasi pesan, atau agregator konten, tag Open Graph (og:image) tidak dapat menemukan sumber yang jelas untuk ditampilkan, sehingga secara drastis menurunkan CTR (tingkat klik).
  2. Konsistensi visual dalam tema: Template modern (seperti yang dirancang menggunakan GeneratePress atau GenerateBlocks) mengandalkan gambar unggulan untuk menyusun kisi-kisi arsip, daftar postingan terkait, atau header. Tanpa gambar unggulan tersebut, tata letak akan rusak atau muncul celah yang tidak sejajar.
  3. Penemuan dan umpan (RSS / Google Discover): Alat-alat seperti Google Discover atau pembaca RSS memprioritaskan atau mensyaratkan konten yang dilengkapi dengan gambar mini beresolusi tinggi untuk mempercantik tampilan kartu artikel.

Untuk mengatasi hal ini tanpa harus menggunakan plugin (seperti yang ini) atau proses yang lambat, saya telah membuat potongan kode PHP yang sederhana dan ringan ini, yang secara otomatis menetapkan gambar pertama di setiap postingan sebagai gambar unggulan, langsung dari dasbor WordPress. Jika postingan Anda tidak memiliki gambar sama sekali, Anda dapat menetapkan gambar default dengan menambahkan URL-nya ke dalam kode.

Apa sebenarnya fungsi potongan kode ini?

Kode ini menambahkan alat pemrosesan batch bawaan yang canggih ke daftar postingan WordPress (wp-admin/edit.php):

  • Tambahkan kolom khusus: Buat kolom ‘GambarUnggulan Hilang di daftar posting agar Anda dapat langsung melihat posting mana saja yang tidak memiliki gambar mini.
  • Pemrosesan 3 tahap: Saat Anda mengaktifkan penugasan untuk sebuah postingan, sistem akan mencari gambar sesuai urutan berikut ini:
    1. Periksa apakah ada gambar yang dilampirkan langsung ke postingan tersebut di Perpustakaan Media.
    2. Jika tidak ada lampiran langsung (misalnya, jika lampiran tersebut disisipkan melalui blok gambar atau HTML), telusuri konten untuk mencari tag <img> pertama guna mengekstrak ID-nya menggunakan fungsi attachment_url_to_postid().
    3. Jika entri tersebut sama sekali tidak berisi gambar, sistem akan menetapkan gambar default (cadangan) yang ditentukan dalam konfigurasi.
  • Pemrosesan massal AJAX (pemrosesan batch): Menyertakan tombol di bagian header (“⚡ Tetapkan semua di halaman ini”) yang memproses semua entri yang terlihat di layar secara berurutan menggunakan permintaan asinkron berturut-turut. Anda juga dapat melakukannya secara manual menggunakan tombol terpisah untuk setiap postingan dalam daftar.
  • Saring draf: Secara otomatis mengesampingkan entri yang berstatus draf sehingga Anda dapat berfokus sepenuhnya pada konten yang telah diterbitkan.
  • Kolom yang dapat diurutkan: Memungkinkan Anda mengurutkan daftar sehingga semua entri yang tidak memiliki gambar unggulan dikelompokkan bersama di bagian atas.

Mengapa perangkat ini begitu ringan dan apakah hal itu tidak memengaruhi kinerja server?

Kekhawatiran umum saat menggunakan alat otomatis semacam ini adalah takut database menjadi macet atau memori PHP kelebihan beban pada situs yang memiliki ribuan artikel. Potongan kode ini dirancang sesuai dengan kriteria pengoptimalan berikut:

1. Fungsi ini hanya berjalan di bagian Admin (is_admin())

Kode ini dirancang khusus untuk halaman input panel administrasi (edit.php). Kode ini sama sekali tidak menambah beban apa pun pada permintaan di situs publik. Pengguna Anda dan metrik kecepatan situs tidak akan terpengaruh sama sekali.

2. Arahkan permintaan ke Meta Cache

Untuk menentukan apakah sebuah postingan berisi gambar atau tidak, potongan kode tersebut tidak melakukan pencarian basis data yang rumit untuk setiap baris. Potongan kode tersebut menggunakan kunci metadata _thumbnail_id, yang dimuat WordPress ke dalam memori secara langsung melalui cache metadata saat menampilkan daftar. Tabel tersebut dimuat hampir seketika.

3. Pemrosesan asinkron bertingkat (siklus AJAX berurutan)

Daripada menjalankan kueri besar-besaran pada basis data untuk memperbarui 700 atau 1.000 entri sekaligus (yang akan menyebabkan timeout atau menghabiskan seluruh memori server), tombol ‘Assign All’ memproses entri-entri tersebut satu per satu menggunakan JavaScript promises:

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

Hal ini memastikan penggunaan sumber daya yang stabil dan konsisten, sehingga Anda dapat melihat kemajuan secara real time, baris demi baris.

4. Tidak ada duplikasi berkas

Snippet ini tidak mengunduh, menggabungkan kembali, atau menduplikasi gambar di hard drive Anda. Snippet ini hanya mengambil ID gambar yang sudah ada di Perpustakaan Media Anda dan menghubungkannya ke postingan dengan menetapkan nilai meta_value yang sesuai di tabel wp_postmeta.

Kode (PHP + JavaScript)

Anda dapat menambahkan kode ini ke berkas functions.php tema anak Anda, ke plugin kustom, atau melalui plugin fungsi kustom seperti Code Snippets atau yang sejenisnya.

Catatan: Jangan lupa untuk mengatur variabel $default_image_url pada baris 56 ke URL lengkap dari gambar umum yang ingin Anda tetapkan pada postingan yang tidak memuat gambar apa pun dalam teksnya.

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
}

Bagaimana cara menggunakannya?

  • Buka daftar ‘Posting’ di panel admin Anda.
  • Buka tab ‘Opsi Tampilan’ di bagian atas dan ubah jumlah item yang ditampilkan menjadi 50 atau 100 per halaman. (Mulailah dengan angka yang lebih kecil, lalu tingkatkan secara bertahap jika server Anda merespons dengan baik.)

Menetapkan gambar unggulan yang belum ada secara massal di WordPress. Opsi tampilan

  • Klik pada judul kolom ‘Sorotan yang Belum Ada’ untuk mengurutkan dan mengelompokkan entri yang belum terpenuhi. Di bagian filter, Anda dapat memilih antara ‘Ada’, ‘Belum Ada’, atau ‘Semua’
  • Setelah Anda yakin sudah siap untuk mulai menetapkan gambar unggulan yang belum ada secara berkelompok, klik tombol biru yang bertuliskan ‘Tetapkan semua di halaman ini’ dan biarkan proses berurutan tersebut menyelesaikan penetapan thumbnail untuk kelompok tersebut. Jika Anda lebih suka, Anda bisa menetapkannya satu per satu.
  • Buka halaman berikutnya dan ulangi langkah tersebut sampai Anda selesai merapikan perpustakaan Anda.

Opsional: potongan kode penugasan otomatis

Agar tidak perlu mengulangi tugas ini di masa mendatang, Anda dapat menambahkan potongan kode singkat ini. Snippet ini berjalan di latar belakang hanya saat Anda menyimpan atau mempublikasikan postingan: jika mendeteksi bahwa Anda belum memilih gambar unggulan secara manual, snippet ini secara otomatis akan menetapkan gambar pertama dalam konten (atau gambar pengganti default, yang harus Anda tambahkan di $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 );
        }
    }
}

Tinggalkan komentar

Ada yang ingin dikatakan?

Este blog se aloja en LucusHost

LucusHost, el mejor hosting