0

I’m working on a small plugin - part of it needs to add several meta boxes to all custom post types. I’ve tried looping through my array of custom port types in various ways but I keep getting errors that I’ve already called functions such as add_meta_box. The script below is my latest effort, it’s not saving values from the last three meta boxes (only the first).

I really want to reduce the size of this. I’m using a class, as per some stuff I learned on a plugin course on net tuts. It’s worked ok for other things, but PHP is not my strength and so I’m pretty damn stuck! Can someone help me loop through or pass the array of custom post types to the function add_meta_box?

Here is the part of relevant script, sorry it’s a big large..

//meta boxes...
    public function meta_boxes(){
    //load the array into a var
    $all_post_types = $this->post_types;

        $just_trades = array();
        foreach($all_post_types as $trade){
            $just_trades[] = $trade['post_type_name'];  
        }
        //call the action 
        add_action('add_meta_boxes','make_meta_box');
        function make_meta_box(){
        //make array of all meta boxes we want to show..

        add_meta_box('landline','Landline Phone Number','landline_function',$just_trades);//id, UI, the function, what page it shows on
        add_meta_box('mobile','Mobile Phone Number','mobile_function',$just_trades);//id, UI, the function, what page it shows on
        add_meta_box('email','Email Address','email_function',$just_trades);//id, UI, the function, what page it shows on
        add_meta_box('website','Website URL','website_function',$just_trades);//id, UI, the function, what page it shows on

        }
        function landline_function($post){ // function that makes the HTML for the admin UI
        $landline = get_post_meta($post->ID,'landline',true);// id is available, the key we want, return a single or array value. Single for this.
        ?>
        <label for="landline">Landline Number: </label>
        <input type="text" class="widefat" name="landline" id="landline" value="<?php echo $landline;?>" />
        <?php   
        }
        add_action('save_post','save_landline');
        function save_landline($id){ // ID is available by default 

            if(isset($_POST['landline'])){  
            update_post_meta($id,'landline',strip_tags($_POST['landline']));    
            }

        }
        function mobile_function($post){ // function that makes the HTML for the admin UI
        $mobile = get_post_meta($post->ID,'mobile',true);// id is available, the key we want, return a single or array value. Single for this.
        ?>
        <label for="mobile">Mobile Number: </label>
        <input type="text" class="widefat" name="mobile" id="mobile" value="<?php echo $mobile;?>" />
        <?php   
        }
        add_action('save_post','save_mobile');
        function save_mobile($id){ // ID is available by default 

            if(isset($_POST['mobile'])){    
            update_post_meta($id,'mobile',strip_tags($_POST['mobile']));    
            }

        }
        function email_function($post){ // function that makes the HTML for the admin UI
        $email = get_post_meta($post->ID,'email',true);// id is available, the key we want, return a single or array value. Single for this.
        ?>
        <label for="email">Email: </label>
        <input type="text" class="widefat" name="email" id="email" value="<?php echo $email;?>" />
        <?php   
        }
        add_action('save_post','save_email');
        function save_email($id){ // ID is available by default 

            if(isset($_POST['email'])){ 
            update_post_meta($id,'email',strip_tags($_POST['email']));  
            }

        }
        function website_function($post){ // function that makes the HTML for the admin UI
        $website = get_post_meta($post->ID,'website',true);// id is available, the key we want, return a single or array value. Single for this.
        ?>
        <label for="website">Website: </label>
        <input type="text" class="widefat" name="website" id="website" value="<?php echo $website;?>" />
        <?php   
        }
        add_action('save_post','save_website');
        function save_website($id){ // ID is available by default 

            if(isset($_POST['website'])){   
            update_post_meta($id,'website',strip_tags($_POST['website']));  
            }

        }

    }

..any help would be great. Dan.

4
  • which is the problem: not saving or not adding to all the post types? i took your code out of the public function meta_boxes(){} wrapper and it creates and saves the metaboxes just fine for me. Mar 16, 2012 at 13:59
  • It adds to all the post types and saves now ( I made a couple of small errors, that’s the up to date script running in the thread). I wanted to loop through, so I can add fields very easy, by just adding to an array at the top of the plugin. If I end up with something like 10 fields this seems a good idea to me.
    – Dan
    Mar 16, 2012 at 14:09
  • i should've said i did merge your code w/ Geert's for the foreach loop. why do you need to make 10 metaboxes? couldn't you maybe put all the fields into 1 metabox? home phone and mobile phone are pretty related and i don't think it is crazy for them to be in the same metabox. then you'd only ever have to add a field to the metabox and a field to the save_post function Mar 16, 2012 at 14:15
  • ...why? Well, it would seem in effort to learn something new I’ve made things very complicated. Amazing how dense I can be sometimes! Lots of this could be grouped into a larger meta box with more inputs, I don’t need masses of meta boxes! I’ll go through and make some more changes. This is what happens when you work alone too much :(
    – Dan
    Mar 16, 2012 at 14:23

2 Answers 2

2

Here is a simple example that adds a meta box to all public post types:

// All public post types
$post_types = array_merge(
    array('page' => 'page', 'post' => 'post'),
    get_post_types(array('_builtin' => FALSE)),
);

// Add meta box for each post type
foreach ($post_types as $post_type)
{
    add_meta_box('id', 'title', 'callback', $post_type);
}

WP Codex: get_post_types(), add_meta_box().

3
  • Thanks for your reply - do you know how I’ll integrate that with the save_post action?
    – Dan
    Mar 16, 2012 at 13:19
  • The save_post action should be fired for all post types. You'll only need a single function for it.
    – Geert
    Mar 16, 2012 at 13:32
  • Ok, got all my saves working in one function now, that’s gotten rid of a lump of unneeded code. Do you know how I could cut down the add_meta_box section to just one function and a foreach statement? I’m trying to get my head around using foreach in an object, as I’ve gotten errors loads of times whilst making all this script (in other parts of the plugin, not just here). Is there some syntax I need to know for working with an object? I’ve been googling but nothing smacked me in the face haha
    – Dan
    Mar 16, 2012 at 14:15
0

overhauled some stuff. added a nonce and some other permissions checks on to the save_post action. merged all the meta into 1 array and merged all the fields into 1 meta box. best idea? who knows, but this is almost exactly like the metabox i am working on at the moment. hope it helps.

//call the action 
add_action('add_meta_boxes','make_meta_box');

function make_meta_box(){


  // All public post types
  $post_types = array_merge(
      array('page' => 'page', 'post' => 'post'),
      get_post_types(array('_builtin' => FALSE)) );

  // Add meta box for each post type
    foreach ($post_types as $post_type) {

             //make array of all meta boxes we want to show..
          add_meta_box('contact','Contact Information','contact_function',$post_type);//id, UI, the function, what page it shows on
    }
}

function contact_function($post){ // function that makes the HTML for the admin UI

  // first thing we'll need is a nonce ?>

  <input type="hidden" name="contact_noncename" value="<?php echo wp_create_nonce( "_contact_meta" );?>" />

  <?php

  $meta = get_post_meta($post->ID,'_contact_meta',true);

  // landline phone number
  $landline = isset($meta['landline']) ? $meta['landline'] : "";  ?>
  <label for="landline">Landline Number: </label>
  <input type="text" class="widefat" name="_contact_meta[landline]" id="landline" value="<?php echo $landline;?>" />

  <?php   

  // mobile phone number
  $mobile = isset($meta['mobile']) ? $meta['mobile'] : "";   ?>
  <label for="mobile">Mobile Number: </label>
  <input type="text" class="widefat" name="_contact_meta[mobile]" id="mobile" value="<?php echo $mobile;?>" />

  <?php 

  // email address
  $email = isset($meta['email']) ? $meta['email'] : "";    ?>
  <label for="email">Email: </label>
  <input type="text" class="widefat" name="_contact_meta[email]" id="email" value="<?php echo $email;?>" />

  <?php   

  // website
  $website = isset($meta['website']) ? $meta['website'] : "";  ?>
  <label for="website">Website: </label>
  <input type="text" class="widefat" name="_contact_meta[website]" id="website" value="<?php echo $website;?>" />

  <?php   

}

add_action('save_post','save_contact');

function save_contact($post_id, $post){ // ID is available by default 
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
          return $post->ID;

    if ( !wp_verify_nonce( $_POST['contact_noncename'], "_contact_meta" )) 
        return $post_id;

    // Check permissions
    if ( 'page' == $_POST['post_type'] ) {
      if ( !current_user_can( 'edit_page', $post_id ) )
        return $post_id;
    } else {
      if ( !current_user_can( 'edit_post', $post_id ) )
        return $post_id;
    }

    // sanitize some things : could do a foreach if you want to strip_tags from all
    $_POST['_contact_meta']['landline'] = strip_tags($_POST['_contact_meta']['landline']);
    $_POST['_contact_meta']['mobile'] = strip_tags($_POST['_contact_meta']['mobile']);
    $_POST['_contact_meta']['email'] = strip_tags($_POST['_contact_meta']['email']);
    $_POST['_contact_meta']['website'] = strip_tags($_POST['_contact_meta']['website']);

    update_post_meta($post_id, '_contact_meta', $_POST['_contact_meta']);

}
5
  • I would normally do the permissions, but this site will be run be me alone, I’m trying to get it done fast too! This is very concise looking code though, thank you.
    – Dan
    Mar 16, 2012 at 15:05
  • I know nothing about “nonce”, I’ll have to check it out. I see you added underscores to start of the variable names, this hides that info from custom fields doesn’t it?
    – Dan
    Mar 16, 2012 at 15:07
  • oh noes! you need a nonce. codex.wordpress.org/WordPress_Nonces it is a basic security feature. yes the underscore _ hides it from custom fields... i don't see much harm in that. my clients wouldn't have the first clue about custom fields, you're providing a user interface for them to enter this data, and since all the post meta is now in a single database entry, it'd be difficult to edit properly in the custom fields section (my opinion) Mar 16, 2012 at 15:10
  • haha, well I will look into this nonce business. I have little to offer you in return. Well, I did find something useful the other day but you will probably already know. I was adding custom taxonomies with this plugin, and I was wondering if I could call posts via one taxonomy shared across all six custom post types - as it happens I can. You just pass an array of custom post types to the taxonomy when you register it. WordPress is epic, I can’t learn fast enough.
    – Dan
    Mar 16, 2012 at 15:15
  • all the nonces and permissions help prevent evil things from getting into your database, even if you are the only one working on this site. wordpress IS epic. been working with it for 2 years and still learn new stuff all the time. Mar 16, 2012 at 15:23

Your Answer

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

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