Advanced Custom Fields: Tips ít ai biết

Advanced Custom Fields (ACF) là plugin quen thuộc với những ai làm việc với WordPress. ACF giúp mở rộng khả năng tùy biến nội dung bằng cách thêm field tùy chỉnh, hỗ trợ từ text, select cho đến repeater hay flexible content. Tuy nhiên, không phải ai cũng khai thác hết tiềm năng của ACF. Bài viết này sẽ chia sẻ một số tips ít được biết đến nhưng cực kỳ hữu ích, giúp bạn tận dụng tối đa plugin này.

Advanced Custom Fields: Tips ít ai biết

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


  • Không có bình luận.

Init Toolbox

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...