Nội dung
- shares
- Facebook Messenger
- Gmail
- Viber
- Skype
Trong bài trước mình có hướng dẫn bạn tạo custom fields cho post type một cách nhẹ nhàng sử dụng plugin Advanced Custom Field (ACF). Plugin này không những giúp bạn tạo field mới cho tất cả các kiểu dữ liệu có trong wordpress như ‘post,page,attachment, category,…’ và các post type tạo bởi plugin bạn có kích hoạt nữa.
Mà ACF còn mở rộng thêm field cho bạn tự định nghĩa.
ACF hỗ trợ rất nhiều kiểu field như text, image và WYSIWYS.Tuy nhiên có nhiều trường hợp dự án web của bạn cần tạo ra field mới để lưu và hiển thị dữ liệu, vậy thì làm thế nào?
Trong bài hôm nay các bạn có thêm một công cụ để tùy biến custom fields trong wordpress bằng cách khai phá API của plugin ACF.
Trước tiên bạn tải plugin tạo field mới, demo này cung cấp trên trang http://www.advancedcustomfields.com/resources/creating-a-new-field-type/. Để cho dễ thực hiện bạn tải về sau đó giải nén vào thư mục plugins/
. Hoặc có thể viết vào theme, nhưng mình khuyến khích để nguyên, mỗi field type nên tạo vào plugin để có thể sử dụng cho nhiều theme.
Download plugin: acf-field-type-template. Code trình bầy dưới đây mình sử dụng cho ACF phiên bản 4. Bạn xem thêm file acf-FIELD_NAME-v5.php sẽ có chút khác biệt, hỗ trợ tính năng mới có trong phiên bản 5.
Khởi tạo field
Chúng ta tạo field mới bằng cách tạo lớp mới, kế thừa class acf_field
.
class acf_field_FIELD_NAME extends acf_field { ...
Trong plugin có hỗ trợ 2 phiên bản acf4 và acf5, bạn có thể tạo cả 2 phần code sử dụng cho 1 trong 2 phiên bản nếu tìm thấy.
Khởi tạo một số biến và phương thức quan trọng sau:
$this->defaults
: các options mặc định cho fields. Liệt kê mảng tên option và giá trị mặc định của field này, trong lúc code bạn không cần gọi hàm kiểm tra option có tồn tại chẳng hạn:if( isset('') )
$this->name
: Điền tên trường field (name). Tên trường FIELD_NAME phải trùng với tên file, ie: acf-FIELD_NAME-v4.php nếu không nội dung field tạo bởi hàmcreate_field
sẽ không hiển thị. Xem hàm này ở phía này.$this->label
: nhãn hiển thị cho field.$this->category
: đưa field này vào nhóm field type, plugin có sẵn các nhóm là: Basic, content, Choice, …
Sau khi thiết lập xong biến cấu hình, chúng ta đưa thông tin vào field thông qua gọi constructor của lớp acf_field parent::__construct();
.
Tạo Field options
Tạo options nối tiếp xen thêm vào các options cố định bắt buộc của mọi fields, ví dụ: require, ví dụ sau mình tạo tùy chọn ‘Preview Size’ hiển thị sau option ‘Require?’ xem hình sau:
Để tạo một hoặc nhiều options cho field bạn sử dụng phương thức create_options
.
/* * create_options() * * Create extra options for your field. This is rendered when editing a field. * The value of $field['name'] can be used (like below) to save extra data to the $field * * @type action * @since 3.6 * @date 23/01/13 * * @param $field - an array holding all the field's data */ function create_options( $field ) { // defaults? /* $field = array_merge($this->defaults, $field); */ // key is needed in the field names to correctly save the data $key = $field['name']; // Create Field Options HTML ?> <tr class="field_option field_option_<?php echo $this->name; ?>"> <td class="label"> <label><?php _e("Preview Size",'acf'); ?></label> <p class="description"><?php _e("Thumbnail is advised",'acf'); ?></p> </td> <td> <?php do_action('acf/create_field', array( 'type' => 'radio', 'name' => 'fields['.$key.'][preview_size]', 'value' => $field['preview_size'], 'layout' => 'horizontal', 'choices' => array( 'thumbnail' => __('Thumbnail'), 'something_else' => __('Something Else'), ) )); ?> </td> </tr> <?php }
Bạn có thể sử dụng hook acf/create_field
trong bản 4 để tạo các trường form như radio, select, input.
Tham số $field
chứa mảng gồm tên và giá trị của field, hiển thị dữ liệu này cho nội dung fields tại trang edit. Bản acf 5 thay hook ‘acf/create_field’ với tên hook khác ‘acf/render_field’. Xem thêm.
Lấy các options của field từ database và trước khi hiển thị ở trang quản lý tạo field tại (ACF backend), dữ liệu field options này được sử lý qua hàm load_field
. Nhờ vào đó, bạn có thể sửa bất kỳ option nào trước khi hàm trả về giá trị options mới.
/* * load_field() * * This filter is applied to the $field after it is loaded from the database * * @type filter * @since 3.6 * @date 23/01/13 * * @param $field - the field array holding all the field options * * @return $field - the field array holding all the field options */ function load_field( $field ) { // Note: This function can be removed if not used return $field; }
Và trước khi lưu options vào database, bạn cũng có thể sửa thêm chúng nhờ có hàm update_field
.
/* * update_field() * * This filter is applied to the $field before it is saved to the database * * @type filter * @since 3.6 * @date 23/01/13 * * @param $field - the field array holding all the field options * @param $post_id - the field group ID (post_type = acf) * * @return $field - the modified field */ function update_field( $field, $post_id ) { // Note: This function can be removed if not used return $field; }
HTML tạo giá trị field
Trường acf field có thể không đơn thuần là duy nhất một input, select, radio..theo logic nâng cao bạn có thể tự định nghĩa một field mới được kết hợp giá trị của các form field có điều kiện cấu tạo nên acf field.
Xây dựng nội dung Field bởi hàm create_field
.
/* * create_field() * * Create the HTML interface for your field * * @param $field - an array holding all the field's data * * @type action * @since 3.6 * @date 23/01/13 */ function create_field( $field ) { // defaults? /* $field = array_merge($this->defaults, $field); */ // perhaps use $field['preview_size'] to alter the markup? // create Field HTML ?> <div> noi dung field </div> <?php }
Phần thiết kế HTML này sẽ hiển thị trong trang nhập nội dung field được gắn vào các post type mà bạn chỉ định.
Thiết kế các acf field bởi hook acf/create_field
vào hàm trên và Tất cả field bạn tạo với api acf/create_field
trong hàm hiển thị nội dung field (create_field) sẽ không được tự động lưu lại. Nhớ rằng tham số $field truyền vào hàm ở trên, chứa thông tin về field, không liên quan đến phần nội dung của field, vì bạn đang tùy biến advanced custom field có thể xây dựng field bởi nhiều trường form. Ví dụ $field có giá trị mảng giống như thế này.
Array ( [key] => field_543c6da4eeeb7 [label] => Ngôn ngữ [name] => fields[field_543c6da4eeeb7] [_name] => qtranslate [type] => qlang [order_no] => 0 [instructions] => Bài viết chỉ hiển thị trong ngôn ngữ này? [required] => 0 [id] => acf-field-qtranslate [class] => qlang [conditional_logic] => Array ( [status] => 0 [rules] => Array ( [0] => Array ( [field] => null [operator] => == [value] => ) ) [allorany] => all ) [field_group] => 187 [value] => )
Vì advanced custom fields không phải là một phần trong hệ thống trang sửa bài viết của wordpress giống như meta box custom fields.
Do đó để lưu lại dữ liệu acf là một custom field độc lập được gán vào post, bạn có thể dùng hook save_post
, xem tại đây.
tuy nhiên plugin cũng cung cấp tính năng tương tự giúp bạn cập nhật mọi post meta bởi hook acf/save_post
.
function my_acf_save_post( $post_id ) { // bail early if no ACF data // load from post if( isset($_POST['fields']) ) { $fields = $_POST['fields']; if(is_array($fields)) foreach($fields as $f) { foreach($f as $field=>$val){ update_post_meta($post_id,$field,$val); } } } } // run before ACF saves the $_POST['acf'] data add_action('acf/save_post', 'my_acf_save_post', 1); // run after ACF saves the $_POST['acf'] data add_action('acf/save_post', 'my_acf_save_post', 20);
Lưu ý: từng phiên bản ACF sẽ sử dụng tên hook khác nhau, nếu ‘acf/save_post’ không được bạn thử đổi sang ‘acf_save_post’ nhé, (acf_save_post chấp nhận tại version 3,4) xem chi tiết. Hàm trên sẽ kích hoạt ở 2 vị trí vị trí 20 bạn để nguyên tên hook. Mình test thấy thế và hoạt động đúng, cho dù hook 1 đổi thành ‘acf_save_post’.
Sửa lại hàm create_field, chúng ta sẽ xác định giá trị của acf field vào api tạo field acf/create_field
.
function create_field( $field ) { // defaults? /* $field = array_merge($this->defaults, $field); */ global $post; $key=$field['name']; // create Field HTML $field1=get_post_meta($post->ID,'field1',true); ?> <div> <?php $opts=array( 'type' => 'select', 'name' => 'fields['.$key.'][field1]', 'value' => $field1, 'choices' => array(..) ); do_action('acf/create_field', $opts); ?> </div> <?php }
Chú ý: $key là tên đối tượng của kiểu field, ie: field_543c6da4eeeb7 lấy bởi giá trị $field[‘name’] và thường quản lý chung vào mảng fields như thế này fields[field_543c6da4eeeb7]
. Nếu không có khai báo mảng giống như vậy thì bạn cần bao thêm fields[..] làm như đoạn code trên.
Bạn cũng có thể sửa lại các giá trị fields trước khi cập nhật vào database. Nếu cần thiết thì khai báo hàm update_value
, mặc định với nội dung sau.
/* * update_value() * * This filter is applied to the $value before it is updated in the db * * @type filter * @since 3.6 * @date 23/01/13 * * @param $value - the value which will be saved in the database * @param $post_id - the $post_id of which the value will be saved * @param $field - the field array holding all the field options * * @return $value - the modified value */ function update_value( $value, $post_id, $field ) { // Note: This function can be removed if not used return $value; }
Các lệnh đều có comment chú thích, bạn xem qua code sẽ tự hiểu. Sử lý giá trị của field còn có 3 phương thức: load_value, format_value, format_value_for_api.
- load_value( $value, $post_id, $field ): có thể sửa lại giá trị field trước khi sử dụng sau khi lấy từ database.
- format_value( $value, $post_id, $field ): định dạng dữ liệu trước khi truyền vào action
create_field
. - format_value_for_api( $value, $post_id, $field ): thậm trí sửa giá trị fied ở frontend, sử dụng hàm lấy fields
the_field
Chú ý: nếu cần thiết sửa giá trị field thì tạo các hàm trên không thì thôi sử dụng mặc định.
Ngoài ra, bạn muốn chèn các file thư viện javascript/css, sử dụng cho việc tạo nội dung field, acf_field class xây dựng sẵn hooks admin_enqueue_scripts
, admin_head
tương ứng liên kết với các hàm callback field_group_admin_enqueue_scripts
, field_group_admin_head
.
2 hook này được chạy trong trang quản lý ACF tạo field.
Nếu muốn thêm tài nguyên thư viện js/css tương tự như ở trang quản lý field, nhưng ở trang edit post type có sử dụng field, bạn thêm 2 hàm sau:
input_admin_enqueue_scripts
cho hook admin_enqueue_scripts
.
và input_admin_head
cho hook admin_head
.
Tham khảo một số acffield
1. Nav Menu Field
Download here.
Hướng dẫn qua hình:
Để nhận được bài viết mới vui lòng đăng ký kênh kiến thức WordPress từ A-Z ở Form bên dưới. Bạn cũng có thể nhận được sự trợ giúp trên Twitter và Facebook
- shares
- Facebook Messenger
- Gmail
- Viber
- Skype
Vui Phan says
Cái time picker có chuyển lại được thành 24h không ad
Hoàng Quách says
cái này bạn thay đổi format của date là được
S-HOME says
mình muốn điền tự động nội dung trong 1 field và có link và màu cho chữ thì phải làm sao? giúp mình với.
Hoàng Quách says
bạn liên hệ với mình qua kênh chat trên hoangweb.com để được tư vấn cụ thể nhé
LDC says
VÌ SAO: WordPress tạo các dòng mới trong bảng post_meta về cập nhật bài đăng trong admin trong khi đó tôi có dùng acf pro :
/**
* Add re field group
*/
acf_add_local_field_group( array(
‘key’ => ‘info’,
‘title’ => __( ‘Thông tin’ ),
‘fields’ => array (
array (
‘key’ => ‘cat’,
‘label’ => __( ‘Menu’ ),
‘name’ => ‘cat’,
‘type’ => ‘post_object’,
‘post_type’ => ‘cat’,
‘required’ => true,
),
Mọi thứ ok trong database có dữ liệu post_meta có cột:
meta_id= 10 , post_id= 15, meta_key= cat , meta_value= 1
Mọi thứ đều ổn .
Nếu tôi cập nhật bài đăng WP sẽ thêm dữ liệu trong cột post_meta
meta_id= 10 , post_id= 15, meta_key= cat , meta_value= 2
meta_id= 11 , post_id= 15, meta_key= _cat , meta_value=cat
Ngoài ra mình cập nhập bình thường cũng bị tạo các dòng mới trong bảng post_meta về cập nhật
meta_id= 10 , post_id= 15, meta_key= cat , meta_value= 1
meta_id= 11 , post_id= 15, meta_key= _cat , meta_value=cat
Qua comment này mong được giúp đỡ làm sao để tránh thêm côt post_meta nữa để tránh dữ liệu đata phình to..
Cảm ơn