Sử dụng Local JSON để tăng tốc độ
ACF cho phép lưu cấu hình field group dưới dạng file JSON trong thư mục theme. Khi có thư mục acf-json trong theme, ACF sẽ tự động ghi và đọc cấu hình từ đó, giúp giảm query DB và dễ đồng bộ giữa các môi trường. Bạn cũng có thể tùy biến đường dẫn bằng filter.
// functions.php
// Lưu JSON vào /wp-content/themes/your-theme/acf-json
add_filter('acf/settings/save_json', function ($path) {
return get_stylesheet_directory() . '/acf-json';
});
// Nạp JSON từ nhiều nơi (theme + child theme, v.v.)
add_filter('acf/settings/load_json', function ($paths) {
// Xóa path mặc định
$paths = array();
// Thêm path theme hiện tại
$paths[] = get_stylesheet_directory() . '/acf-json';
// Nếu có child theme, có thể thêm
if (is_child_theme()) {
$paths[] = get_template_directory() . '/acf-json';
}
return $paths;
});
Tích hợp ACF với REST API
Mặc định, WordPress REST API không tự trả về tất cả custom fields của ACF. Cách an toàn và phổ biến là đăng ký thêm trường REST cho post type cần thiết và trả về dữ liệu từ get_fields(). Cách này không phụ thuộc plugin ngoài.
// functions.php
// Expose toàn bộ ACF fields của post qua REST API: /wp-json/wp/v2/post/ID
add_action('rest_api_init', function () {
register_rest_field(
['post', 'page', 'manga'], // liệt kê post types bạn muốn
'acf',
[
'get_callback' => function ($object) {
// $object['id'] là post ID
$fields = get_fields($object['id']);
return $fields ? $fields : (object)[];
},
'schema' => null,
]
);
});
Tối ưu query với get_fields()
Thay vì gọi nhiều lần get_field(), hãy lấy một lần rồi dùng lại. Điều này giảm chi phí truy vấn, đặc biệt ở template lặp lớn.
// Trong loop template
$post_id = get_the_ID();
// Lấy 1 lần
$acf = get_fields($post_id);
// Dùng lại nhiều nơi
$title_alt = $acf['title_alt'] ?? '';
$rating = $acf['rating'] ?? 0;
$gallery = $acf['gallery'] ?? []; // ví dụ là repeater hoặc gallery
if ($title_alt) {
echo '<h2 class="entry-alt">' . esc_html($title_alt) . '</h2>';
}
if (!empty($gallery)) {
echo '<div class="gallery">';
foreach ($gallery as $item) {
$img = $item['image'] ?? null;
if (!empty($img['url'])) {
printf(
'<img src="%s" alt="%s">',
esc_url($img['url']),
esc_attr($img['alt'] ?? '')
);
}
}
echo '</div>';
}
Tạo Global Options Page
Dùng Options Page để lưu dữ liệu dùng chung toàn site (logo, hotline, social link, script tracking…). Dữ liệu được truy vấn bằng get_field('key', 'option').
// functions.php
if (function_exists('acf_add_options_page')) {
acf_add_options_page([
'page_title' => 'Site Settings',
'menu_title' => 'Site Settings',
'menu_slug' => 'site-settings',
'capability' => 'manage_options',
'redirect' => false,
'position' => 59
]);
}
// Ở bất kỳ template nào:
$hotline = get_field('hotline', 'option');
$facebook = get_field('facebook_url', 'option');
if ($hotline) {
echo '<a href="tel:' . esc_attr($hotline) . '" class="hotline">' . esc_html($hotline) . '</a>';
}
Kết hợp Conditional Logic nâng cao
Conditional Logic giúp UI nhập liệu gọn gàng hơn. Ở phía frontend, bạn vẫn nên kiểm tra điều kiện trước khi render để tránh rác HTML.
// Ví dụ: chỉ hiển thị iframe YouTube nếu loại media là "video" và có URL
$media_type = get_field('media_type'); // select: "image" | "video"
$youtube = get_field('youtube_url');
if ($media_type === 'video' && $youtube) {
// Chuyển URL sang embed nếu cần
$embed = preg_replace('~watch\\?v=([\\w-]+)~', 'embed/$1', $youtube);
echo '<div class="video"><iframe src="' . esc_url($embed) . '" loading="lazy" allowfullscreen></iframe></div>';
} else {
// Render ảnh fallback
$image = get_field('featured_image');
if (!empty($image['url'])) {
echo '<img src="' . esc_url($image['url']) . '" alt="' . esc_attr($image['alt'] ?? '') . '">';
}
}
Tận dụng ACF Blocks trong Gutenberg
ACF cho phép tạo block tùy biến bằng PHP, nhẹ và dễ kiểm soát. Đăng ký block với acf_register_block_type(), sau đó render bằng callback/template.
// functions.php
add_action('acf/init', function () {
if (function_exists('acf_register_block_type')) {
acf_register_block_type([
'name' => 'cta-box',
'title' => __('CTA Box'),
'description' => __('Hộp kêu gọi hành động có tiêu đề, mô tả, nút'),
'category' => 'widgets',
'icon' => 'megaphone',
'keywords' => ['cta', 'button', 'box'],
'mode' => 'preview',
'supports' => [
'align' => false,
'jsx' => false
],
'render_callback' => function ($block, $content = '', $is_preview = false, $post_id = 0) {
$title = get_field('title') ?: 'Title';
$desc = get_field('description') ?: '';
$btn_txt = get_field('button_text') ?: 'Learn more';
$btn_url = get_field('button_url') ?: '#';
echo '<div class="cta-box">';
echo '<h3>' . esc_html($title) . '</h3>';
if ($desc) {
echo '<p>' . esc_html($desc) . '</p>';
}
echo '<a class="btn" href="' . esc_url($btn_url) . '">' . esc_html($btn_txt) . '</a>';
echo '</div>';
},
]);
}
});
Dùng Field Groups như Template Content
Khi nhiều post type dùng chung cấu trúc, hãy dùng trường Clone để tái sử dụng nhóm field, hoặc export/import JSON để áp vào dự án khác. Dưới đây là ví dụ export PHP để có thể versioning trong code.
// Ví dụ: nạp field groups bằng PHP (đã export từ ACF)
// functions.php
add_action('acf/include_fields', function () {
if (!function_exists('acf_add_local_field_group')) {
return;
}
acf_add_local_field_group([
'key' => 'group_seo_shared',
'title' => 'SEO Shared',
'fields' => [
[
'key' => 'field_meta_title',
'label' => 'Meta Title',
'name' => 'meta_title',
'type' => 'text',
],
[
'key' => 'field_meta_desc',
'label' => 'Meta Description',
'name' => 'meta_description',
'type' => 'textarea',
'rows' => 3,
],
],
'location' => [
[
[
'param' => 'post_type',
'operator' => '==',
'value' => 'post',
],
],
],
]);
});
Bonus: Tạo helper an toàn để render field
Tạo một helper nhỏ giúp thoát dữ liệu đúng cách và giảm lặp code khi in ra HTML.
// functions.php
function im_field($key, $fallback = '', $post_id = null) {
$val = get_field($key, $post_id);
if (is_string($val)) {
return esc_html($val);
}
if (is_array($val) && isset($val['url'])) {
return esc_url($val['url']);
}
return $fallback;
}
// template usage
printf('<a href="%s" class="btn">%s</a>',
esc_url(get_field('button_url') ?: '#'),
im_field('button_text', 'Read more')
);
Kết luận
Advanced Custom Fields không chỉ là công cụ thêm field đơn giản, mà còn là nền tảng mạnh mẽ để xây dựng hệ thống dữ liệu tùy biến trong WordPress. Với các tips kèm snippet ở trên, bạn có thể tăng hiệu suất, tối ưu workflow, tích hợp dữ liệu qua REST API và chuẩn hóa cách tái sử dụng field group. Hãy đưa chúng vào theme/plugin của bạn và đo ngay hiệu quả về tốc độ cũng như chất lượng phát triển.
Bình luận