PHP Warning with Custom Fields

Update 29.6.19

I think the array_map() error is actually caused by how the selects are named. They have names like tax_input[fuel-type], which probably results in them getting passed to the default taxonomy saving function. As only single value is passed for each select and I assume the tax save handler expects an array, the array_map() warning is raised.

This would also explain why some of the values weren’t saved. The values weren’t in $_POST[$valid_taxonomy], but $_POST['tax_input'][$valid_taxonomy] (meta_boxes.php:416). I missed this when I wrote my loop examples.

You could experiment with either changing the select names to name="tax_slug" or by changing the names to array format name="tax_input[fuel-type][]". foreach ( $valid_taxonomies as $valid_taxonomy ) should start working with the former option and would be unnecessary with the latter.

Try replacing meta_boxes.php lines 59-60 with wp_nonce_field( 'save_car_details_meta', 'nonce_car_details'); and lines 361-363 with check_admin_referer( 'save_car_details_meta', 'nonce_car_details' );. Do similiar thing for the testimonials metabox and its saving function.


New answer

I had a quick glance on your code on GitHub and I think something like this should make it work.

Replace lines 372 – 518 with the code below. Have a helper array with valid keys that you compare the $_POST against. Loop meta and term data separately and save them accordingly – meta data as post meta, set term data as post terms.

if ( 'revision' === $post->post_type ) {
  return;
};

$valid_meta_keys = array(
  '_vin',
  '_mileage',
  '_intcol',
  '_tot',
  '_nod',
  '_trim',
  '_price',
);
foreach ( $valid_meta_keys as $valid_meta_key ) {
  $current_value = get_post_meta( $post->ID, $valid_meta_key, FALSE );
  $new_value = isset( $_POST[$valid_meta_key] ) ? $_POST[$valid_meta_key] : '';

  if ( ! $new_value && ! $current_value ) {
    delete_post_meta($post->ID, $valid_meta_key);
    continue;
  } else if ( ! $new_value ) {
    continue;
  }

  // If $value is an array, make it a CSV (unlikely)
  if ( is_array( $new_value ) ) {
    $new_value = implode(',', $new_value);    
  }

  // Returns meta_id if the meta doesn't exist, otherwise returns true on success and false on failure. It also returns false if the value submitted is the same as the value that is already in the database. 
  update_post_meta($post->ID, $valid_meta_key, sanitize_text_field( $new_value ) );
}

$valid_taxonomies = array(
  'makes',
  'model_year',
  'body_type',
  'colors',
  'drivetrain',
  'transmissions',
  'fuel-type',
  'engine',  
);
foreach ( $valid_taxonomies as $valid_taxonomy ) {
  $new_value = isset( $_POST[$valid_taxonomy] ) ? intval( $_POST[$valid_taxonomy] ) : NULL;
  // Replace previous terms or clear with NULL $new_value
  wp_set_object_terms( $post->ID, $new_value, $valid_taxonomy, false );
}

Replace lines 597 – 610 with the code below. No need for a loop here as there’s only one meta key.

$customer_name = isset( $_POST['_customer'] ) ? $_POST['_customer']: '';
if ( get_post_meta( $post->ID, '_customer', FALSE ) ) {
  update_post_meta($post->ID, '_customer', sanitize_text_field( $customer_name ) );
} else {
  delete_post_meta($post->ID, '_customer');
}

First answer

As Jacob Peattie pointed out in his comment, your question has quite a lot of code, which makes it rather difficult to review.

But based on the screenshots you’ve provided, you should dig into the theme files noted on the PHP warnings and add some guard clauses to the related lines. Here are some general examples,

Undefined index

// key is set in array and the value is not empty
if ( ! empty( $array['some_key'] ) ) {
  // some code
}

or

// key is set in array, but value can be empty
if ( isset( $array['some_key'] ) ) {
  // some code
}

argument should be an array or invalid argument supplied for foreach

// make sure the variable is array
if ( is_array( $something ) ) {
  // foreach loops
  // array_maps
}

undefined variable

// variable exists and is different than NULL
if ( isset( $variable ) ) {
  // some code
}

or

// variable exists and value equals FALSE
if ( ! empty( $variable ) ) {
  // some code
}

Do add fallbacks for ifs with elses, if needed. E.g.

  • add key to array with empty or some default value
  • set variable
  • cast variable to array