WordPress: Tạo ảnh thumbnail dự phòng linh hoạt

Khi xem danh sách bài trong các chuyên mục hoặc theo từ khoá trên luom.tv, những bài không có “featured image” tự dưng làm cho tổng thể trông hơi lổn nhổn. Anh bèn gu-gờ “WordPress fallback thumbnail image”.

Kết quả là có sẵn plugin, nhưng anh thấy không cần thiết phải phức tạp thế. Sau biết là có thể dùng add_filter cho post_thumbnail_html rất đơn giản kiểu như này:

function luomtv_fallback_post_thumbnail_html( $html, $post_id, $post_thumbnail_id ) {

    if ( empty( $html ) && !is_single() ) {
        $html = '<img src="/link/to/a/static/photo" />';
    }
    return $html;
}
add_filter( 'post_thumbnail_html', 'luomtv_fallback_post_thumbnail_html', 5, 3 );

Ban đầu anh cũng làm một cái ảnh cố định, nhưng thấy nó hơi đơn điệu nên chuyển sang dùng SVG với màu nền ngẫu nhiên.

function luomtv_fallback_post_thumbnail_html( $html, $post_id, $post_thumbnail_id ) {
    
    $colors = array("B1B2FF", "AAC4FF", "D2DAFF", "EEF1FF");

    if ( empty( $html ) && !is_single() ) {
        $rand_key = array_rand($colors);

        $html = '<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 480 320" style="border-radius: 8px;">'
        . '<rect fill="#' . $colors[$rand_key] . '" width="100%" height="100%"></rect></svg>';
    }

    return $html;
}

add_filter( 'post_thumbnail_html', 'luomtv_fallback_post_thumbnail_html', 5, 3 );

Bảng màu được định nghĩa trong biến $colors là được lấy từ Color Hunt.

Đây là kết quả và so sánh giữa có và không có ảnh thay thế:

So sánh giữa có và không có ảnh thay thế

Hiện tại thì ảnh thay thế này anh để một màu trơn. Còn khả năng của SVG thì rất lớn, nên ai muốn vẽ thêm gì vào cũng được.

Cập nhật

Sau khi đăng bài này thì anh thấy đúng là cũng nên thêm cái gì đó vào thật. Chẳng phải nghĩ lâu, anh sẽ cho chữ cái hoặc chữ số đầu tiên trong tên bài viết vào cho đỡ trống trải.

Cái này lúc đầu tưởng đơn giản vì chỉ cần dùng hàm mb_substr() là được. Tuy nhiên, thực tế là phải lọc trước một số thứ đi đã.

  1. Bỏ hết các thẻ HTML, chỉ giữ lại phần văn bản thô (text).
  2. Một số kí tự đặc biệt thì WordPress chuyển sang dạng HTML Entity, ví dụ dấu ngoặc kép mở “ thì nó chuyển thành &#8220; nên là phải “giải mã” nó về dạng một kí tự đã.
  3. Kí tự đầu tiên trong tiêu đề không phải là chữ cái hay số thì phải bỏ đi, ví dụ dấu ngoặc vuông [ trong “[Slide]”.
  4. Sau khi đã lấy được kí tự đầu tiên rồi thì nó có thể là chữ có dấu thanh điệu (ví dụ “Ảnh”), vậy thì phải bỏ dấu thanh: Ả > A, Ẩ > Â v.v.

Cụ thể là như này:

// Loại bỏ thẻ HTML
$title = strip_tags( get_the_title() );

// "Giải mã" các kí tự dạng HTML entity
$title = html_entity_decode( $title );

// Bỏ các kí tự không phải chữ cái hoặc số
$title = preg_replace('/[^\p{L}\p{N}]/u', '', $title );

// Lấy ra kí tự đầu tiên trong tiêu đề
$character = mb_substr( $title, 0, 1);

// Loại bỏ dấu thanh tiếng Việt
$character = luomtv_remove_tonemarks($character);

Trước đó thì phải định nghĩa hàm luomtv_remove_tonemarks() như này:

function luomtv_remove_tonemarks($text) {
  $from = array(
    '/[àảãáạ]/u', '/[ằẳẵắặ]/u', '/[ầẩẫấậ]/u', '/[ÀẢÃÁẠ]/u', '/[ẰẲẴẮẶ]/u', '/[ẦẨẪẤẬ]/u',
    '/[èẻẽéẹ]/u', '/[ềểễếệ]/u', '/[ÈẺẼÉẸ]/u', '/[ỀỂỄẾỆ]/u',
    '/[ìỉĩíị]/u', '/[ÌỈĨÍỊ]/u',
    '/[òỏõóọ]/u', '/[ồổỗốộ]/u', '/[ờởỡớợ]/u', '/[ÒỎÕÓỌ]/u', '/[ỒỔỖỐỘ]/u', '/[ỜỞỠỚỢ]/u',
    '/[ùủũúụ]/u', '/[ừửữứự]/u', '/[ÙỦŨÚỤ]/u', '/[ỪỬỮỨỰ]/u',
    '/[ỳỷỹýỵ]/u', '/[ỲỶỸÝỴ]/u'
  );

  $to = array(
    'a', 'ă', 'â', 'A', 'Ă', 'Â',
    'e', 'ê', 'E', 'Ê',
    'i', 'I',
    'o', 'ô', 'ơ', 'O', 'Ô', 'Ơ',
    'u', 'ư', 'U', 'Ư',
    'y', 'Y'
  );
  return preg_replace($from, $to, $text);
}

Đến đây thì anh thấy nó cũng hơi bị cồng kềnh rồi. Nhưng thôi, đã đâm lao phải the lao. Đoạn $html ở trên sẽ được bổ sung thêm thẻ <text> sau thẻ <rect>:

'<text x="50%" y="60%" dominant-baseline="middle" text-anchor="middle" text-decoration="none" font-size="280" fill="orange" fill-opacity="0.4">' . $character . '</text>'

Kết quả:

Danh sách bài viết
Dấu thanh ở “Í” đã được loại bỏ; các dấu chấm và dấu trắng đã được loại bỏ để “Ê” trở thành kí tự đầu tiên

Lưu ý là ảnh này chỉ hiển thị trên trang, còn để hiển thị khi chia sẻ trên Facebook thì phải làm một cái ảnh tĩnh và cho vào <head> kiểu như này:

function luomtv_head() { 
  if ( is_single() && !has_post_thumbnail() ) {
    echo '<meta property="og:image" content="https://luom.tv/linhtinh/2022/09/LuomTV-thumbnail-1000.png" />';
  }
}

add_action('wp_head', 'luomtv_head');

Một bình luận

  1. […] trước, khi tạo ảnh đại diện dự phòng cho bài, có đoạn anh dùng PHP để bỏ dấu thanh điệu. Thực ra trước đó ở Dự án S […]