Tự động set featured image cho bài viết

Cập nhật lần cuối vào

Bài viết này mình sẽ hướng dẫn cho bạn cách để tự động thêm featured image hay còn gọi là tự động tạo thumbnail cho bài viết trên WordPress. Để có thể đọc tiếp và thực hiện theo nội dung của bài này thì bạn hãy quay lại xem bài cách lấy hình ảnh đầu tiên trong bài viết của WordPress.

Nếu như bạn đã hiểu và biết cách để tự động lấy thông tin hình ảnh từ bài viết rồi thì bây giờ bạn tiếp tục thực hiện theo cách mà mình hướng dẫn bên dưới để tự động set featured image cho bài viết.

function sb_get_image_attachments($post_id) {
	return get_children(array('post_parent' => $post_id, 'post_type' => 'attachment', 'post_mime_type' => 'image'));
}

function sb_get_first_image_attachment($post_id) {
	$attach_images = sb_get_image_attachments($post_id);
	$result = null;
	if(count($attach_images) > 0) {
		$result = array_shift($attach_images);
	}
	return $result;
}

function sb_set_post_thumbnail($post_id) {
	if(current_theme_supports('post-thumbnails') && !has_post_thumbnail($post_id)) {
		$first_image = sb_get_first_image_attachment($post_id);
		if($first_image) {
			set_post_thumbnail($post_id, $first_image->ID);
			return true;
		}
	}
	return false;
}

function sb_auto_set_thumbnail($post_id) {
	if (wp_is_post_revision($post_id)) {
        return;
    }
	sb_set_post_thumbnail($post_id);
}
add_action('save_post', 'sb_auto_set_thumbnail');

Đoạn code bên trên sẽ tự động tạo thumbnail cho bài viết của bạn khi bạn nhấn nút lưu hoặc là khi bạn nhấn vào nút publish bài viết. Nếu trong trường hợp bài viết của bạn đã có thumbnail hoặc là không có hình ảnh nào được đính kèm vào nội dung của bài viết thì sẽ không có chuyện gì xảy ra. Ngược lại, nếu bên trong nội dung bài viết của bạn có đính kèm hình ảnh thì hình ảnh đầu tiên được đính kèm sẽ lấy để tạo ảnh thumbnail cho bài viết.

Trong trường hợp giao diện hiện tại không bật chức năng hỗ trợ thumbnail thì hàm bên trên cũng sẽ không làm gì cả.

Tạo thumbnail từ đường dẫn bên ngoài

Trường hợp ở bên trên như bạn thấy thì đó mới chỉ là cái đơn giản, bây giờ nếu bạn muốn tạo thumbnail từ hình ảnh bên ngoài thì phải làm như thế nào?

Ý tưởng của thuật toán ở đây: Bạn phải tải hình ảnh từ bên ngoài về và lưu vào thư mục uploads của WordPress, sau đó bạn cho hình ảnh đó vào thư viên media của WordPress. Cuối cùng là bạn lấy hình ảnh media đó để tạo thumbnail cho bài viết.

function sb_get_first_image_url_from_text($content) {
	$doc = new DOMDocument();
	@$doc->loadHTML($content);
	$xpath = new DOMXPath($doc);
	$src = $xpath->evaluate('string(//img/@src)');
	return $src;
}

function sb_get_image_attachments($post_id) {
	return get_children(array('post_parent' => $post_id, 'post_type' => 'attachment', 'post_mime_type' => 'image'));
}

function sb_get_first_image_attachment($post_id) {
	$attach_images = sb_get_image_attachments($post_id);
	$result = null;
	if(count($attach_images) > 0) {
		$result = array_shift($attach_images);
	}
	return $result;
}

function sb_create_folder($file_path) {
	if(!file_exists($file_path)) {
		mkdir($file_path);
	}
}

function sb_copy($source, $destination) {
	if(@fclose(@fopen($source, 'r'))) {
		copy($source, $destination);
		return true;
	}
	return false;
}

function sb_insert_attachment($attachment, $file_path) {
	if(!file_exists($file_path)) {
		return 0;
	}
	$file_type = wp_check_filetype(basename($file_path), null);
	$attachment['post_mime_type'] = $file_type['type'];
	if(!isset($attachment['guid'])) {
		return 0;
	}
	$attachment['post_status'] = isset($attachment['post_status']) ? $attachment['post_status'] : 'inherit';
	if(!isset($attachment['post_title'])) {
		$attachment['post_title'] = preg_replace('/\.[^.]+$/', '', basename($file_path));
	}
	$attach_id = wp_insert_attachment($attachment, $file_path);
	if($attach_id > 0) {
		sb_update_attachment_meta($attach_id, $file_path);
	}
	return $attach_id;
}

function sb_update_attachment_meta($attach_id, $file_path) {
	if(!function_exists('wp_generate_attachment_metadata')) {
		require_once(ABSPATH . 'wp-admin/includes/image.php');
	}
	$attach_data = wp_generate_attachment_metadata($attach_id, $file_path);
	wp_update_attachment_metadata($attach_id, $attach_data);
}

function sb_fetch_media($image_url) {
	$attach_id = 0;
	$wp_upload_dir = wp_upload_dir();
	$base_dir = trailingslashit($wp_upload_dir['basedir']) . 'sb-media';
	$base_url = trailingslashit($wp_upload_dir['url']) . 'sb-media';
	sb_create_folder(($base_dir);
	$parts = pathinfo($image_url);
	$random = rand();
	$random = md5($random);
	$file_name = 'sb-media-' . $parts['filename'] . '-' . $random . '.' . $parts['extension'];
	$file_path = trailingslashit($base_dir) . $file_name;
	$file_url = trailingslashit($base_url) . $file_name;
	if(sb_copy($image_url, $file_path)) {
		$attachment = array(
			'guid' => $file_url
		);
		$attach_id = sb_insert_attachment($attachment, $file_path);
	}
	return $attach_id;
}

function sb_set_post_thumbnail($post_id) {
	if(current_theme_supports('post-thumbnails') && !has_post_thumbnail($post_id)) {
		$first_image = sb_get_first_image_attachment($post_id);
		if($first_image) {
			set_post_thumbnail($post_id, $first_image->ID);
			return true;
		} else {
			$post = get_post($post_id);
			if($post) {
				$first_image = sb_get_first_image_url_from_text($post->post_content);
				$attach_id = sb_fetch_media($first_image);
				if($attach_id > 0) {
					set_post_thumbnail($post_id, $attach_id);
					return true;
				}
			}
		}
	}
	return false;
}

function sb_auto_set_thumbnail($post_id) {
	if (wp_is_post_revision($post_id)) {
        return;
    }
	sb_set_post_thumbnail($post_id);
}
add_action('save_post', 'sb_auto_set_thumbnail');

Trong ví dụ bên trên, mình sẽ chạy code để lấy hình ảnh được đính kèm đầu tiên trước, nếu bài viết không có hình ảnh đính kèm thì sẽ tìm đường dẫn đầu tiên trong bài viết. Mình sẽ tải hình ảnh đó về và lưu vào thư mục uploads của WordPress, tập tin được đặt trong thư mục sb-media.

function sb_fetch_media($image_url) {
	$attach_id = 0;
	$wp_upload_dir = wp_upload_dir();
	$base_dir = trailingslashit($wp_upload_dir['basedir']) . 'sb-media';
	$base_url = trailingslashit($wp_upload_dir['url']) . 'sb-media';
	sb_create_folder(($base_dir);
	$parts = pathinfo($image_url);
	$random = rand();
	$random = md5($random);
	$file_name = 'sb-media-' . $parts['filename'] . '-' . $random . '.' . $parts['extension'];
	$file_path = trailingslashit($base_dir) . $file_name;
	$file_url = trailingslashit($base_url) . $file_name;
	if(sb_copy($image_url, $file_path)) {
		$attachment = array(
			'guid' => $file_url
		);
		$attach_id = sb_insert_attachment($attachment, $file_path);
	}
	return $attach_id;
}

Sau khi tải hình ảnh về rồi thì mình sẽ sử dụng hàm wp_insert_attachment để thêm hình ảnh vừa rồi vào thư viện media của WordPress.

function sb_insert_attachment($attachment, $file_path) {
	if(!file_exists($file_path)) {
		return 0;
	}
	$file_type = wp_check_filetype(basename($file_path), null);
	$attachment['post_mime_type'] = $file_type['type'];
	if(!isset($attachment['guid'])) {
		return 0;
	}
	$attachment['post_status'] = isset($attachment['post_status']) ? $attachment['post_status'] : 'inherit';
	if(!isset($attachment['post_title'])) {
		$attachment['post_title'] = preg_replace('/\.[^.]+$/', '', basename($file_path));
	}
	$attach_id = wp_insert_attachment($attachment, $file_path);
	if($attach_id > 0) {
		sb_update_attachment_meta($attach_id, $file_path);
	}
	return $attach_id;
}

Sau khi chèn xong media thì chúng ta lại tiếp tục cập nhật lại thông tin cho hình ảnh này, bao gồm cả quá trình khởi tạo ra các hình ảnh thu nhỏ hoặc phóng to tùy theo kích thước đã khai báo bằng hàm add_image_size.

function sb_update_attachment_meta($attach_id, $file_path) {
	if(!function_exists('wp_generate_attachment_metadata')) {
		require_once(ABSPATH . 'wp-admin/includes/image.php');
	}
	$attach_data = wp_generate_attachment_metadata($attach_id, $file_path);
	wp_update_attachment_metadata($attach_id, $attach_data);
}

Vậy là qua bài viết này bạn đã có thể biết thêm được cách để tự động gán thumbnail cho bài viết. Không chỉ gán bằng hình ản bạn đã upload sẵn trong thư viên media của WordPress, mà bạn còn có thể gán thumbnail bằng đường dẫn của hình ảnh bên ngoài, tuy nhiên thì nếu bạn gặp trường hợp server của hình ảnh bạn muốn lấy không cho phép bạn truy cập và tải hình ảnh thì kết quả của hàm sẽ không thực hiện được.