0

I've got a frontend form with text, select and checkbox inputs the text and selects update and work just fine, using update_post_meta() however the checkboxes aren't updating. Since they're stored in a serialized array do I need to use a different function or just set it up differently?

update_post_meta($post_id, 'appliances', esc_attr(strip_tags($_POST['customMetaAppliances[]'])));

Here's the code to output the checkboxes on the frontend as well, which is working perfectly, its just that the checked options aren't saving to the database.

<?php

$allCheckbox = get_field('appliances'); //Checked value from backend

$field_key = "field_5a0a1264370c0"; //Get value using key
$post_id = get_the_ID();
$field = get_field_object($field_key, $post_id);
$count = 0;
foreach($field['choices'] as $lab => $val){
if(is_array($allCheckbox) && in_array($val, $allCheckbox)){
    $checked = 'checked = "checked"';   
    //$enable = '';       
} else {
    $checked = '';
    //$enable = 'disabled=""';
}
?>
<li><input type="checkbox" name="customMetaAppliances[]" id="customMetaAppliances" value="<?php echo $lab; ?>" <?php echo $checked; ?> /><label><?php echo $val; ?></label></li>
<?php 
    $count++;
    if ($count == 3) {
        echo '</ul><ul class="propfeatures col span_6">';
        $count = 0;
    }
} ?>

When viewing the row within the database this is whats being passed, so the array of checkboxes is being ignored?

enter image description here

UPDATE:

enter image description here

So this makes sense but it seems the array from name="customMetaAppliances[]" isn't being passed from the checkboxes? What do you guys think?

4
  • I don't think ACF saves to a meta like that. did you see this guide: advancedcustomfields.com/resources/create-a-front-end-form ? 2ndly your code above doesn't start the unordered list and will cut one off if there are three items in your list as well start another at the same time if you ever have 3 items. After that they are off on their own again.
    – rudtek
    Commented Dec 6, 2017 at 23:24
  • The other ACF fields text and select save just fine with update_post_meta() which leads me to believe its just a syntax problem with checkboxes or something else I need to do, the acf_form() function isn't an option as the entire form is a mix of CMB2 created fields and ACF, also the acf_form() function is basically for just editing regular posts on the front end not a custom form. Commented Dec 7, 2017 at 23:15
  • I've also tried using their update_field() instead same thing… Commented Dec 7, 2017 at 23:24
  • Updated the original with a reply from ACF support, so its just the array from name="customMetaAppliances[]" is not being passed, any idea? Commented Dec 8, 2017 at 20:00

2 Answers 2

1

To be compatible with ACF you should first find out how ACF is saving checkboxes values to database. As I now this is serialized array. When we know that we must save our frontend checkboxes in the same way. The good news is you can pass only array to update_post_meta and WordPress will take care of serialization.

The problem with your code is that you probably not passing array of checkbox values. You should investigate this part: esc_attr(strip_tags($_POST['customMetaAppliances[]'])).

Two things which bother me here:

  • esc_attr and strip_tags functions are expecting string as argument not an array they may return unexpected results
  • if you want to get array of checkboxes from post request you should use field name without square brackets customMetaAppliances

I think you can replace saving part with code:

$customMetaAppliances = filter_input( INPUT_POST, 'customMetaAppliances', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
update_field( 'customMetaAppliances', $customMetaAppliances, $post_id );

Personaly when I have installed ACF I use update_field instead of update_post_meta.

I created fully working class which will display form on the frontend after post content and save values to post ACF fields on submit.

class WPSE_287946_Form {

    /**
     * Class constructor
     */
    public function __construct() {

        $this->define_hooks();
    }

    public function save_form() {

        if( isset( $_POST['save'] ) ) { // Submit button

            $post_id     = filter_input( INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT );
            $name        = filter_input( INPUT_POST, 'name', FILTER_SANITIZE_STRING );
            $color       = filter_input( INPUT_POST, 'color', FILTER_SANITIZE_STRING );
            $accessories = filter_input( INPUT_POST, 'accessories', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );

            update_field( 'name', $name, $post_id );
            update_field( 'color', $color, $post_id );
            update_field( 'accessories', $accessories, $post_id );

            // Redirect user because POST request on single post page will trigger 404 page.
            wp_redirect( get_permalink( $post_id ) );
        }
    }

    /**
     * Display form
     */
    public function display_form( $content ) {

        $name        = get_field( 'name' );
        $color       = get_field( 'color' );
        $accessories = get_field( 'accessories' );

        ob_start();

        ?>

        <form method="post">
            <p>
                <?php $this->display_text( 'name', 'Name', $name ); ?>
            </p>
            <p>
                <?php $this->display_select( 'color', 'Color', $this->get_available_colors(), $color ); ?>
            </p>
            <p>
                <?php $this->display_checkboxes( 'accessories', 'Accessories', $this->get_available_accessories(), $accessories ); ?>
            </p>
            <p>
                <input type="hidden" name="id" value="<?php esc_attr_e( get_the_ID() ) ?>">
                <input type="submit" name="save" value="Submit" />
            </p>
        </form>

        <?php

        $output = ob_get_contents();
        ob_end_clean();

        return $content . $output;
    }

    /**
     * Display text field
     */
    private function display_text( $name, $label, $value = '' ) {
        ?>
        <label><?php esc_html_e( $label, 'wpse_287946' ) ?></label>
        <input type="text" name="<?php esc_attr_e( $name ) ?>" value="<?php esc_attr_e( $value ); ?>">
        <?php
    }

    /**
     * Display select field
     */
    private function display_select( $name, $label, $options, $value = '' ) {
        ?>
        <label><?php esc_html_e( $label, 'wpse_287946' ) ?></label>
        <select name="<?php esc_attr_e( $name ) ?>">
            <?php $this->display_options( $options, $value ); ?>
        </select>
        <?php
    }

    /**
     * Display options
     */
    private function display_options( $options, $value ) {

        foreach( $options as $option_value => $option_label ):
            $selected = ( $option_value === $value ) ? ' selected' : '';
            ?>
            <option value="<?php esc_attr_e( $option_value ) ?>"<?php esc_attr_e( $selected ) ?>><?php esc_html_e( $option_label, 'wpse_287946' ) ?></option>
            <?php

        endforeach;
    }

    /**
     * Display checkboxes field
     */
    private function display_checkboxes( $name, $label, $options, $values = array() ) {

        $name .= '[]';

        ?>
        <label><?php esc_html_e( $label, 'wpse_287946' ) ?></label>
        <?php

        foreach ( $options as $option_value => $option_label ):
            $this->display_checkbox( $name, $option_label, $option_value, $values );
        endforeach;
    }

    /**
     * Display single checkbox field
     */
    private function display_checkbox( $name, $label, $available_value, $values = array() ) {
        $checked = ( in_array($available_value, $values) ) ? ' checked' : '';
        ?>
        <label>
            <input type="checkbox" name="<?php esc_attr_e( $name ) ?>" value="<?php esc_attr_e( $available_value ) ?>"<?php esc_attr_e( $checked ) ?>>
            <?php esc_html_e( $label, 'wpse_287946' ) ?>
        </label>
        <?php
    }

    /**
     * Get available colors
     */
    private function get_available_colors() {

        return array(
            'red' => 'Red',
            'blue' => 'Blue',
            'green' => 'Green',
        );
    }

    /**
     * Get available accessories
     */
    private function get_available_accessories() {

        return array(
            'case' => 'Case',
            'tempered_glass' => 'Tempered glass',
            'headphones' => 'Headphones',
        );
    }

    /**
     * Define hooks related to plugin
     */
    private function define_hooks() {

        /**
         * Add action to save form
         */
        add_action( 'wp', array( $this, 'save_form' ) );

        /**
         * Add filter to display form
         */
        add_filter( 'the_content', array( $this, 'display_form' ) );
    }
}

new WPSE_287946_Form();
1
  • You're the man, worked like a charm — thanks so much!!!! Commented Dec 10, 2017 at 18:03
0

Shouldn't the name of the checkbox be name="customMetaAppliances[]" ? That way you get an array of them in $_POST. now you're passing just the value of last one in the form, if it's not checked it's empty, and not saved.

2
  • That makes total sense since it is an array, made the change but they're still not updating on the backend? Commented Dec 6, 2017 at 23:09
  • Updated the original with a reply from ACF support, so its just the array from name="customMetaAppliances[]" is not being passed, any idea? Commented Dec 8, 2017 at 20:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.