
چند دن پہلے، میں نے ایک طویل التوا میں پڑا ہوا کام مکمل کیا جو کرنا ضروری تھا، لیکن میں اسے برسوں سے ٹالتا رہا تھا۔ میں نےتمامغائب فیچرڈ تصاویربازیاب کیںاور تصاویر میں تمام غائب متبادل متن شامل کیا۔ میں نے تمام غائب میٹا ڈسکرپشنز لکھنے کا کام بھی مکمل کیا۔ کُل ملا کر، میں نے اپنے تیار کردہ تین مختصر کوڈ کے ٹکڑوں کا استعمال کرتے ہوئے 15,000 سے زائد ریکارڈز میں اضافہ یا ترمیم کی۔ آج میں یہاں گمشدہ فیچرڈ تصاویر بازیاب کرنے والا وہ کوڈ ٹکڑا شیئر کر رہا ہوں، جسے میں نے دوسری سائٹس پر بھی یہ کام انجام دینے کے لیے استعمال کیا۔
اگر آپ کافی عرصے سے بلاگنگ کر رہے ہیں تو بہت ممکن ہے کہ آپ کے پاس کچھ پرانی پوسٹس ہوں جن کے لیے فیچرڈ امیج مقرر نہیں کیا گیا ہو۔ یہ کلاسیکی ایڈیٹر کے زمانے میں اکثر ہوتا تھا، جب ہم تصویر کو براہِ راست پوسٹ کے متن میں شامل کر لیتے تھے لیکن اسے 'فیچرڈ امیج' کے خانے میں منتخب کرنا بھول جاتے تھے۔
پوسٹس کو فیچرڈ امیج کے بغیر چھوڑنا صرف جمالیاتی مسئلہ نہیں ہے، بلکہ یہ آپ کی سائٹ کی اصلاح اور صارف کے تجربے کو براہِ راست متاثر کرتا ہے۔
- سوشل SEO اور اوپن گراف: جب پوسٹ کو سوشل میڈیا، میسجنگ ایپس یا مواد کے مجموعہ کاروں پر شیئر کیا جاتا ہے، تو اوپن گراف ٹیگز (
og:image) پیش کرنے کے لیے کوئی واضح وسیلہ نہیں مل پاتا، جس سے CTR (کلک تھرو ریٹ) میں نمایاں کمی واقع ہوتی ہے۔ - تیم میں بصری یکسانیت: جدید ٹیمپلیٹس (جیسے GeneratePress یا GenerateBlocks کے ذریعے ڈیزائن کیے گئے) آرکائیو گرڈز، متعلقہ پوسٹس کی فہرستیں یا ہیڈرز بنانے کے لیے فیچرڈ امیج پر انحصار کرتے ہیں۔ اس کے بغیر لے آؤٹ ٹوٹ جاتا ہے یا بے ترتیب خالی جگہیں رہ جاتی ہیں۔
- ڈسکوری اور فیڈز (RSS / گوگل ڈسکوری): گوگل ڈسکوری یا RSS ریڈرز جیسے ٹولز آرٹیکل کارڈ کو بہتر بنانے کے لیے ایسے مواد کو ترجیح دیتے ہیں یا ضروری قرار دیتے ہیں جن کے ساتھ اعلیٰ ریزولوشن تھمب نیل منسلک ہو۔
پلگ انز (جیسے یہ پلگ ان) یا سست عمل کے استعمال کے بغیر اس مسئلے کو حل کرنے کے لیے، میں نے یہ سادہ اور ہلکا پھلکا PHP سنیپ شاٹ تیار کیا ہے جو ورڈپریس ڈیش بورڈ سے براہ راست ہر پوسٹ کی پہلی تصویر کو فیچرڈ امیج کے طور پر خود بخود سیٹ کر دیتا ہے۔ اگر آپ کی پوسٹ میں کوئی تصویر نہیں ہے تو آپ کوڈ میں اس کی URL شامل کر کے ایک ڈیفالٹ تصویر مقرر کر سکتے ہیں۔
یہ سنیپ شاٹ بالکل کیا کرتا ہے؟
یہ کوڈ ورڈپریس پوسٹ لسٹ (wp-admin/edit.php) میں ایک سمارٹ، بلٹ ان بیچ پروسیسنگ ٹول شامل کرتا ہے:
- ایک حسبِ ضرورت کالم شامل کریں: پوسٹس کی فہرست میں 'غائب فیچرڈ امیج' کالم بنائیں تاکہ ایک نظر میں معلوم ہو سکے کہ کون سی پوسٹس کے تھمبنیل غائب ہیں۔
- 3-تہہ پراسیسنگ: جب آپ کسی پوسٹ کے لیے اسائنمنٹ فعال کرتے ہیں، تو یہ بالکل اسی ترتیب میں تصویر تلاش کرتا ہے:
- چیک کریں کہ آیا میڈیا لائبریری میں پوسٹ کے ساتھ براہِ راست کوئی تصاویر منسلک ہیں یا نہیں۔
- اگر کوئی براہِ راست منسلک فائل نہ ہو (مثال کے طور پر اگر وہ امیج بلاک یا HTML کے ذریعے داخل کی گئی ہوں)، تو content کو اسکین کریں اور پہلی
<span>img</span>ٹیگ تلاش کر کےattachment_url_to_postid()استعمال کرتے ہوئے اس کی ID نکالیں۔ - اگر اندراج میں بالکل بھی تصاویر نہ ہوں تو یہ کنفیگریشن میں متعین کردہ ڈیفالٹ (فال بیک) تصویر مقرر کر دیتا ہے۔
- AJAX بلک پراسیسنگ (بیچ پراسیسنگ): ہیڈر میں ایک بٹن ( "⚡ اس صفحے پر تمام تفویض کریں") شامل ہے جو اسکرین پر دکھائی دینے والی تمام اندراجات کو متواتر غیر ہم وقت درخواستوں کے ذریعے ترتیب وار پراسیس کرتا ہے۔ آپ فہرست میں ہر پوسٹ کے لیے موجود انفرادی بٹن استعمال کرکے بھی یہ کام دستی طور پر کر سکتے ہیں۔
- ڈرافٹ فلٹر: خودکار طور پر ڈرافٹ اسٹیٹس میں موجود اندراجات کو خارج کر دیتا ہے تاکہ آپ صرف شائع شدہ مواد پر توجہ مرکوز کر سکیں۔
- ترتیب دینے والا کالم: آپ کو فہرست کو اس طرح ترتیب دینے کی اجازت دیتا ہے کہ فیچرڈ امیج کے بغیر تمام اندراجات اوپر ایک ساتھ گروپ ہو جائیں۔
یہ اتنا ہلکا کیوں ہے اور کیا یہ سرور کی کارکردگی کو متاثر نہیں کرتا؟
اس قسم کے خودکار ٹول کے استعمال کے دوران ایک عام تشویش یہ ہوتی ہے کہ ہزاروں مضامین والی سائٹس پر ڈیٹا بیس لاک ہو جائے یا PHP میموری اوورلوڈ ہو جائے۔ یہ سنیپ شاٹ درج ذیل اصلاحی معیار کے مطابق ڈیزائن کیا گیا ہے:
1. یہ صرف ایڈمن سیکشن میں چلتا ہے (is_admin())
یہ کوڈ خصوصی طور پر انتظامی پینل کی ان پٹ اسکرین (edit.php) کے لیے پیک کیا گیا ہے۔ یہ عوامی سائٹ پر کی جانے والی درخواستوں میں ایک بھی اضافی لائن شامل نہیں کرتا۔ آپ کے صارفین اور رفتار کے اعدادوشمار کسی بھی طرح متاثر نہیں ہوں گے۔
2. میٹا کیش کو براہِ راست استفسارات کریں۔
یہ جاننے کے لیے کہ کسی پوسٹ میں تصویر ہے یا نہیں، یہ سنیپ شاٹ ہر قطار کے لیے پیچیدہ ڈیٹا بیس تلاش نہیں کرتا۔ یہ _thumbnail_id میٹا ڈیٹا کلید استعمال کرتا ہے، جسے ورڈپریس فہرست پیش کرتے وقت میٹا ڈیٹا کیش کے ذریعے بذاتِ خود میموری میں لوڈ کرتا ہے۔ جدول تقریباً فوری طور پر لوڈ ہو جاتی ہے۔
3. آبشار وار غیر ہم آہنگ عمل (ترتیبی AJAX لوپ)
ڈیٹا بیس پر ایک بہت بڑا سوال چلانے کے بجائے کہ ایک ہی بار میں 700 یا 1,000 اندراجات کو اپ ڈیٹ کیا جائے (جس سے ٹائم آؤٹ ہو سکتا ہے یا سرور کی ساری میموری استعمال ہو سکتی ہے)، 'Assign All' بٹن جاوا اسکرپٹ پرومِسز استعمال کرتے ہوئے اندراجات کو ایک ایک کر کے پراسیس کرتا ہے:
پوسٹ 1 (AJAX)⟶ٹھیک جواب⟶پوسٹ 2 (AJAX)⟶ٹھیک جواب…
یہ وسائل کے مستحکم اور یکساں استعمال کو یقینی بناتا ہے، جس سے آپ قطار بہ قطار حقیقی وقت میں پیش رفت دیکھ سکتے ہیں۔
۴۔ فائل کی نقل نہ کریں
یہ سنیپ شاٹ آپ کی ہارڈ ڈرائیو پر تصاویر ڈاؤن لوڈ، دوبارہ جوڑ یا نقل نہیں کرتا۔ یہ صرف آپ کی میڈیا لائبریری میں پہلے سے موجود تصویر کی آئی ڈی لے کر اسے wp_postmeta ٹیبل میں متعلقہ meta_value تفویض کرکے پوسٹ سے منسلک کرتا ہے۔
کوڈ (پی ایچ پی + جاوا اسکرپٹ)
آپ یہ کوڈ اپنی چائلڈ تھیم کی functions.php فائل میں، کسی کسٹم پلگ ان میں، یا Code Snippets ج یسے کسٹم فنکشنز پلگ ان کے ذریعے شامل کر سکتے ہیں۔
نوٹ: لائن 56 پر
`$default_image_url`متغیر کو اس عمومی تصویر کے مکمل یو آر ایل پر سیٹ کرنا یاد رکھیں جسے آپ ان پوسٹس میں تفویض کرنا چاہتے ہیں جن کے متن میں کوئی تصویر شامل نہیں ہے۔
پی ایچ پی
// 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
}
آپ اسے کیسے استعمال کرتے ہیں؟
- اپنے ایڈمن پینل میں 'پوسٹس' کی فہرست پر جائیں۔
- اوپر موجود 'ڈسپلے آپشنز' ٹیب کھولیں اور فی صفحہ دکھائے جانے والے آئٹمز کی تعداد 50 یا 100 کر دیں۔ (چھوٹی تعداد سے شروع کریں اور اگر آپ کا سرور اچھی کارکردگی دکھائے تو بتدریج بڑھائیں۔)

- باقی ماندہ اندراجات کو ترتیب دینے اور گروپ کرنے کے لیے 'Missing Highlights' کالم کے ہیڈر پر کلک کریں۔ فلٹرز میں آپ 'Has'، 'Missing' یا 'All' میں سے انتخاب کر سکتے ہیں۔
- جب آپ اس بات سے مطمئن ہو جائیں کہ آپ غائب فیچرڈ تصاویر کو بیچوں میں تفویض کرنا شروع کرنے کے لیے تیار ہیں، تو نیلے ' ' بٹن پر کلک کریں جس پر 'اس صفحے کی تمام تصاویر کو تفویض کریں' لکھا ہے، اور اس بیچ کے تھمب نیلز کی تفویض مکمل ہونے دیں۔ اگر آپ چاہیں تو انہیں ایک ایک کر کے بھی تفویض کر سکتے ہیں۔
- اگلے صفحے پر جائیں اور اپنی لائبریری کی صفائی مکمل ہونے تک یہ عمل دہرائیں۔
اختیاری: خودکار تفویض کا ٹکڑا
مستقبل میں اس کام کو دوبارہ کرنے سے بچنے کے لیے، آپ یہ مختصر کوڈ کا ٹکڑا شامل کر سکتے ہیں۔ یہ صرف پسِ منظر میں اس وقت چلتا ہے جب آپ کوئی پوسٹ محفوظ یا شائع کرتے ہیں: اگر یہ محسوس کرے کہ آپ نے دستی طور پر فیچرڈ امیج منتخب نہیں کی، تو یہ خودبخود مواد میں موجود پہلی تصویر (یا ڈیفالٹ فال بیک امیج، جسے آپ کو $default_image_url = میں شامل کرنا ہوگا) مقرر کر دیتا ہے۔
پی ایچ پی
// 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 );
}
}
}







