Hello,
I insert via the add_post_meta() function some information in my custom posts. Everything works fine for the classic fields however, I have 3 checkboxes that I would like to fill as well but the code in the DB seems serialized?
I would like to use :
add_post_meta($ID_post, 'wpcf-format-de-l-evenement', $Array_Events);
The storage format for checkboxes fields is complicated, and while you can output checkboxes fields using types shortcodes or the types_render API function, there is no official API support for setting checkboxes programmatically.
I wrote an unofficial API function to allow setting/getting checkboxes options which I will share below, together with some examples of how to use it.
Please review and try to use that instead of the core add_post_meta function.
/**
* Unofficial API function to check/uncheck checkboxes options
*
* @param int $post_id
* @param string $field // slug of checkboxes field
* @param string $option // title of checkbox option to manipulate
* @param string $action : 'check' | 'uncheck' | 'value' (default, returns current value)
*
* Important: assumes recommended checkboxes setting of save nothing to database when unchecked
*/
function ts_checkboxes( $post_id, $field, $option, $action = 'value' ){
if ( isset($post_id) && isset($field) && isset($option) ){
$field_settings = types_get_field( $field );
$field_options = $field_settings['data']['options'];
// Locate the option key
$key = array_search( $option, array_column( $field_options, 'title' ) );
$keys = array_keys( $field_options );
$option_key = $keys[$key];
// Get the current post meta value
$meta = get_post_meta( $post_id, 'wpcf-'.$field, true );
// If action = 'value' just return the value
if ( $action == 'value' && isset( $meta[$option_key] ) ){
return $meta[$option_key][0];
} else {
// Remove the existing key if it exists (i.e. uncheck)
// because recommended setting is to save nothing when unchecked
unset( $meta[$option_key] );
// If $checked == true then add back the key + value
if ( $action == 'check' ){
$meta[$option_key] = array($field_options[$option_key]['set_value']);
}
update_post_meta( $post_id, 'wpcf-'.$field, $meta );
}
}
}
Examples of how to then use this function would be:
// 1. Get the value of the option "Second checkbox" of a checkboxes field "Available options" from the current post:
global $post;
$value = ts_checkboxes( $post->ID, 'Available options', 'Second checkbox' );
// 2. set the same option as checked
global $post;
ts_checkboxes( $post->ID, 'Available options', 'Second checkbox', 'check' );
// 3. set the same option as unchecked
global $post;
ts_checkboxes( $post->ID, 'Available options', 'Second checkbox', 'uncheck' );
Hopefully you can follow that and adapt the examples to your needs.
I've tried your code : something doesn't seem to work.
When I mill your function by injecting the values:
$post_id = 1200
$field = wpcf-event-format
$option = 'Workshop'
$action = 'check'
The function executes well (no stoppage) until the end but my page (ID = 1200) still does not have the 'Workshop' box checked in the 'event-format'.
When I echo 'update_post_meta' before inserting, I get: update_post_meta( 1200, wpcf-event-format, A );
It looks like the variable $meta (= A) forgets to take information into account (at least the famous $option = 'Workshop')..
And a print_r($meta); give me too the 'A' ..
So something goes wrong next to the line $meta = get_post_meta( $post_id, $field, true );
I re-tested this on my own site again and it works fine, every time, it's not clear why it wouldn't be working on your site.
Where you added the print_r($meta) statement for debugging, can you move that to immediately after the line $meta = get_post_meta( $post_id, 'wpcf-'.$field, true );
What does it show then when you are running this again:
I will try to tell you more:
Your initial function doesn't work on my code (maybe that's where there's something to unblock..) --> the function abruptly stopped when executing the line "unset( $meta[$option_key] );"
As this line was about (according to your comment on the code) the case of an already existing key (which is not the case here since the custom field is by default empty at the creation of a new page.) I had voluntarily removed it and the code continued its execution until the end.
2 things then :
- The print_r(meta) always returns only 'A', even with your initial function (which seems normal since this line is above the unset( $meta[$option_key] );)
- The unset( $meta[$option_key] ); line doesn't seem to work and blocks the function in its execution.
OK, I think you must be running PHP 8.x which is more strict about applying unset.
I've updated the code to handle the case when there is no existing value for the field so that it works okay in PHP 8+ as well as in PHP 7 (and I tested with PHP 8.1).
/**
* Unofficial API function to check/uncheck checkboxes options
*
* @param int $post_id
* @param string $field // slug of checkboxes field
* @param string $option // title of checkbox option to manipulate
* @param string $action : 'check' | 'uncheck' | 'value' (default, returns current value)
*
* Important: assumes recommended checkboxes setting of save nothing to database when unchecked
*/
function ts_checkboxes( $post_id, $field, $option, $action = 'value' ){
if ( isset($post_id) && isset($field) && isset($option) ){
$field_settings = types_get_field( $field );
$field_options = $field_settings['data']['options'];
// Locate the option key
$key = array_search( $option, array_column( $field_options, 'title' ) );
$keys = array_keys( $field_options );
$option_key = $keys[$key];
// Get the current post meta value
$meta = get_post_meta( $post_id, 'wpcf-'.$field, true );
if ( !is_array($meta) ){
$meta = [];
}
// If action = 'value' just return the value
if ( $action == 'value' && isset( $meta[$option_key] ) ){
return $meta[$option_key][0];
} else {
// Remove the existing key if it exists (i.e. uncheck)
// because recommended setting is to save nothing when unchecked
unset( $meta[$option_key] );
// If $checked == true then add back the key + value
if ( $action == 'check' ){
$meta[$option_key] = array($field_options[$option_key]['set_value']);
}
update_post_meta( $post_id, 'wpcf-'.$field, $meta );
}
}
}
Great!
Indeed, the problem is solved with your arrangement for PhP 8.0.
My ts_checkboxes( $ID_post_cree, 'format-de-l-evenement', 'Atelier', 'check' ); works perfectly.
I have one more thing to deal with... the arrays.
Indeed, I sometimes have several boxes checked. These boxes are input type="checkbox" name="format-event[]"
So I would like to call the function :
ts_checkboxes( $ID_post_cree, 'format-de-l-evenement', $_POST['format-event'] , 'check' );
But apparently it doesn't work... the echo shows me :
update_post_meta( 1230, format-de-l-evenement, Array );
The array is not perfectly integrated... do you have a suggestion?
The function ts_checkboxes is intended to update one option at a time, so if you have an array of options in the $_POST object then you would need to loop over them with a foreach loop and call ts_checkboxes for each option.