Blog

Sharing WordPress tips and tricks as I find them

Admin Pages with Genesis

One of the best new features of Genesis 1.8 (and there are many) is a tool for making admin pages. These are needed if you’re building a plugin or a complex theme with site-wide settings that need to be managed.

I recently built an Event Manager theme for promoting an event, and on our Event Theme Settings page we had fields for event date and location, so these could be used throughout the site and pulled from a single source.

This code is pretty technical, but it is 100x easier than making admin pages without Genesis. See this 10 page tutorial by Chip Bennett for instructions on making them without Genesis’ help.

You should only use this method if you’re building a Genesis theme or a Genesis-specific plugin. If you build a plugin for public distribution, make sure you put some checks in place to ensure the user is running Genesis (take a look at the AgentPress plugin code as an example).

Here’s the steps:

  1. Specify the page information. This includes the page’s name and default values for your fields.
  2. Create the sanitization filters. These keep the page secure by ensuring the right type of data are entered.
  3. Set up the help tab, a very useful feature that was improved in WordPress 3.3.
  4. Add your metaboxes to the page.
  5. Build your metaboxes.
  6. Finally, add the new admin page to the backend.

For a complete example, see the child-theme-settings.php file in my base child theme.

Specify the page information

First, it’s best to keep all this code in its own file so your theme is easy to browse. I like to create a “lib” folder in my child theme where I store everything. In my example, I created /lib/admin/child-theme-settings.php, then added this to my functions.php to include it:

Now inside your child-theme-settings.php file, place the following:

This is a lot of code, so I’ll walk through it:

  • I start out with some page-specific documentation that describes what this page is (always a good practice).
  • Then there’s the documentation for our new class, Child_Theme_Settings
  • We create our new class by extending the existing Genesis_Admin_Boxes class
  • First thing in our new class is the __construct() method (functions inside of classes are called methods). This is what sets everything up.
  • We create an unique page ID for this page. I’m calling mine ‘child’, but you could call yours whatever you’d like. I recommend naming it the same as your child theme since it will contain your child-theme-specific settings.
  • Next we specify some information about the menu item. It’s a child of the ‘genesis’ page, we give it a page title and a menu title.
  • Then we create the $page_ops variable which lets you customize some page settings. I’ve left the defaults in there and commented them out so you can see. Uncomment a line and then modify it to change the default.
  • Then we define the settings field. All the settings on this page will be grouped together. If you create a field called address you can get to it like this: $address = genesis_get_option( 'option_name', 'child-settings' );
  • Finally, we create the admin page by adding all the variables together in the create() method.
  • I’ve also added the sanitation action (in __construct() method) and sanitization_filters() method to create the sanitization filters, which we’ll do in the next step.

Before we move on, a few quick notes about classes. Everything inside the class should use the __construct() method for hooking to appropriate actions/filters. Classes are their own namespace, so you can name the methods whatever you’d like. Unlike standard functions where you always need to prefix, you don’t have to worry about any other function having the same name. And finally, when hooking methods to actions make sure you use array( $this, 'method_name' ) instead of just 'method_name'.

Create the sanitization filters

Sanitization is about ensuring the data collected is the type of data you expect. By limiting a checkbox to a 0 or 1, a title to no html… you’re able to prevent code you didn’t expect (whether malicious or not) from altering the way your theme/plugin works.

See my previous post on Genesis options for more details on sanitization filters.

I’m planning to have two fields on this page – phone and address – so I’ll register those as no_html. Update your sanitization_filters() method like this:

Help Tab

While not required, it’s a good idea to put instructions and other useful information in the help tab. If you’d like to have a help tab, simply create a help() method in your class.

Here’s a screenshot of the help tab in my Event Theme. I don’t usually provide this much information, but the client plans to sell the theme so we wanted to provide as much information as possible.

To create a help tab, add this method inside your Child_Theme_Settings class ( so before the last } ).

Provide an unique ID for the tab, then give it a title (shown on the left) and HTML content (shown on the right). For multiple tabs, simply repeat the $screen->add_help_tab() method inside your help() method.

Add your metaboxes

We’ll now create a method inside our class called metaboxes(). For each metabox we’d like to add to our page, we’ll write a simple one line of code to add_meta_box().

I’ve added a single metabox with an ID of ‘contact-information’, a title of ‘Contact Information’, a callback function (where the actual metabox code is) of contact_information(), I’m putting it on the current page, it goes in the main column (not that there’s any other columns for it) and I want it positioned at the top. For more information on this function, see add_meta_box() in the Codex.

Build your metaboxes

In the previous method we referenced a callback function called contact_information(). Now it’s time to build this.

My metabox, Contact Information, will contain two fields. Phone will be a text field, and Address is a textarea. For examples of more fields, look at the actual Genesis admin pages (/lib/admin/…). And I’ve heard there might be a tool similar to our Custom Metabox Library for making Genesis admin fields (talk with NickTheGeek).

This method also goes inside your Child_Theme_Settings class.

The important thing to note here is the handy methods that are built into the class (examples below are for the field ‘phone’ ).

  • $this->get_field_name( 'phone' );
  • $this->get_field_id( 'phone' );
  • $this->get_field_value( 'phone' );

That’s It!

That’s all it takes to build custom admin pages in Genesis. The code definitely looks complicated, but once you get started it’s pretty easy to modify it to your needs. StudioPress has done all the hard (and repetitive) work for you, so you just have to specify the things that are unique to the page.

Here’s the completed code:

And once you do have your custom admin page up-and-running, you’ll need to access that information. Just use genesis_get_option( [field-name], [settings-field] );.

So in the above example, to access the phone number use: $phone = genesis_get_option( 'phone', 'child-settings' );.

28 Comments

  1. Hi, Bill – I just wanted to thank you for these tutorials. My skills aren’t good enough yet that I can really put them into practice at this point, but I save them all to Evernote so I can come back to them when I am ready to put them into effect. The detailed explanations you provide are very helpful.

  2. Great tutorial, you can make it even simpler though. I took the Custom Metabox class and built my own class to extend this. Now I just need one class for my plugins, and any custom stuff from my themes. Interacting with it is much easier than building a new class every time. You can see it in work on my Genesis Simple Breadcrumbs and Genesis Simple Comments plugins right now. I’ll be getting it on git once I figure out why it is denying my access to push or commit right now.

    • How to make file upload work?

      • Bill Erickson says:

        I don’t have a file uploader in my code. Take a look at Nick’s to see if he has one, or the Options Framework.

        • Oh yeah sorry, I was pointing to Nick plugin and yes, I was playing around with his plugins but the file upload didn’t work. Need a bit tweak but beyond my knowledge right now :(
          I do use Options Framework mostly, it just I want to be consistent with the Genesis Framework settings.
          Perhaps there will be a library or classes to extend Genesis Admin Settings in future, similar as CMB :)

  3. Great tutorial.
    One question tho. Is it possible to modify the data entered in the settings fields before it reaches the database?
    Following your example, what if I could store several phones and addresses inside an array. And the next time the page is loaded you could insert a new phone and address but also edit the ones you have already entered.
    Is this possible with the way genesis builds options pages or that should be done in the old way?

    • Bill Erickson says:

      I don’t see any reason why you couldn’t do that in this instance. You have complete control of the actual fields in the page. All this class does is allow you to easily add the page.

  4. Hi Bill, thank you for this great tutorial! I have a Multisite install and I want to have a network activated plugin with this function. How can I make it working in a plugin? Right now, it is not working as a plugin, it gives an error.

    Thank you for your support!

    • Bill Erickson says:

      To be honest I’ve never worked in a MultiSite environment so I can’t provide guidance on that. But you might look at how the existing StudioPress plugins add their option pages.

      Before you load your code you’ll need to check to see if Genesis is running. Look in the AgentPress Listings plugin for an example of that (I use that often in my plugins).

  5. Nice tut.

    What would be the best practive to do this in a plugin. I get a error that the class not exists. Wrapping the class extend into a function and hook it into “after_setup_theme” solves this, would that be a good way to do it?

    • Bill Erickson says:

      Since it’s an admin menu and should only run in Genesis is active, I use the ‘genesis_admin_menu’ hook. See the last line here: http://plugins.svn.wordpress.org/genesis-grid-loop/tags/1.1/plugin.php

      • Ah thanks for the fast reply, my guess was right, ‘genesis_admin_menu’ is a better fit then ‘after_setup_theme’.

        Looks like i have to really get to know the entire genesis admin class, for my special purposes i would have to extend it and not the metaboxes class, because i need boxes only on the right and no save and reset buttons on the top and bottom.

  6. Thanks for this helpful tut.

    There is a tiny error i found:
    ‘save_notice_text’ should be ‘saved_notice_text’

  7. This has worked perfectly for me. BUT, I have a question: I’m trying to get it to load as a main menu item on the same level as Genesis, not a submenu of Genesis. I’ve tried extending the “Genesis_Admin_Settings” class, but no luck. Any tips?

  8. I am using this tutorial for a plugin and am getting an error: “fatal error: class genesis admin boxes not found”. I’ve used this for a child theme and it worked fine. Any special considerations when you extend the admin class for a plugin?

  9. Thanks for this tut, helped me kickstart a plugin.

    Not sure why you not approved my last comment, or did I forget to send it or something? A few days ago I mentioned a missing d in line 51 of the full gist, just wanted to help others who might wondering why custom save messages not show up. Looks like this is based on a older genesis version or something the error text line is also missing I just found out.

    Look at this gist for explanation https://gist.github.com/nextgenthemes/5191011

    Pull requests for gists would be cool ;)

  10. Thanks for your resources, Bill. They are very helpful.

    I’m having an issue when creating an admin metabox and calling that information on a specific page in my site (the homepage). It looks like it is saving multiple instances of information in the database, and only pulling the first instance of information – so I can’t update the content at all! It’s simply only pulling the first information that I entered, and won’t update accordingly.

    Any ideas on why this is? It’s probably easy, but I’m a newbie coder, so it’s driving me nuts! Thanks again!

  11. Bill,
    thanks for the tut, very clear.

    question:
    If i’m including a color picker in the options, this kind of thing is typically implemented in css, as opposed to inside a php file / template like I might do with a more content oriented field like phone or address.

    For example, if I created a color chooser in the child theme options with the idea of using that as a custom page background color I could alter the child theme template code to include inline styling with call to that custom options field.

    But do you have any advice in calling these options purely in custom style files?

    Is that even recommended, or would I have to always alter tempalte codes with inline styling to access these custom options?

    Thanks.

    Craig

    • Bill Erickson says:

      Unfortunately you’ll have to add inline styles. Hook a function to wp_head and output your styles there. This is how custom headers and backgrounds are currently handled in WordPress core.

      • Thanks Bill.

        I took a look at http://codex.wordpress.org/Custom_Backgrounds, which looks pretty much like what you’re referring to in terms of output html.

        Maybe this is a stupid question, but is there a benefit then to going through the settings api, as opposed to just using an admin page with meta boxes like you show here or another options page / framework – if the output is essentially going to be rendered the same way?

        What I’m trying to reconcile is performance and standards vs. ease of use for client when making some theme and post options available for custom jobs.

  12. Hi Bill,

    Thanks for this great tutorial! Works perfect.

    Is it possible to remove the reset button from $page_ops . I don’t want my users to hit it accidentally and remove all data.

    Many thanks.

    Best regards,

    Stefan

  13. Hello Bill,
    Thanks for posting this, this is very helpful!

    Kind regards,
    Rian

Join the Conversation

If you'd like to include code in your post, please post it to http://gist.github.com and include a link.