Adding a select box with categories into WordPress’ theme customizer

WP_themecusto

Note: for some awesome examples written by the WP team, check out their Github page with some great examples.

No more option pages

The WordPress theme customizer is the coolest thing since sliced bread. Maybe now, we as developers can all get on the same page when making WordPress themes. I’ve been playing with the theme customizer API and I think the days of theme options are numbered. I mean, do we really need pages and pages of theme options? I guess I can see it for overly complex WordPress as a giant CMS project. But the average blogger only needs a few powerful options.

If you’re starting a theme from scratch, I highly recommend working with Underscores, the starter theme from Automattic. This article assumes you’re using it. If you’re not, it still may work, you may just need to make some adjustments.

Keeping it modular

I wouldn’t recommend polluting your functions.php file with all this customizer code. If you’re using Underscores, they already scaffold out inc/customizer.php, then import it into function.php, which is super convenient.

If you didn’t know, there’s 3 parts to using WordPress’ theme customizer. You need a section, a control and a setting. I’ll explain more as we go.

Go into inc/customizer.php and lets make a section. Add this within the themename_customize_register( $wp_customize ) function

$wp_customize->add_section('mytheme_options', array(
  'title'    => __('Front Page Categories', 'themename'),
  'priority' => 120,
));

This creates a section for our control to live in. The control is literally the thing that you’ll be clicking on and selecting your category. So lets add the control to the section we just made:

$wp_customize->add_control( 'cat_1', array(
  'settings' => 'cat_1',
  'label'    => 'Left Box',
  'section'  => 'mytheme_options',
  'type'     => 'select',
  'choices'  => get_categories_select()
));

To do this correctly, in my opinion, we want 'choices' to take associative array in this form:

array (
  'slug' => 'Category Name'
)

If we do it like this we can use the ‘slug’ for the WP_Query (and to lookup anything else we want about the category) and ‘Category Name’ for what is displayed to the user. So here’s the function I referenced above called get_categories_select()

function get_categories_select() {
  $teh_cats = get_categories();
  $results;

  $count = count($teh_cats);
  for ($i=0; $i < $count; $i++) {
    if (isset($teh_cats[$i]))
      $results[$teh_cats[$i]->slug] = $teh_cats[$i]->name;
    else
      $count++;
  }
  return $results;
}

Awesome, now we need to create a place to store this setting. Thus, we should create the last part of the theme customizer’s holy trinity, the setting. This is what lets you retrieve the data you entered into the control.

$wp_customize->add_setting('cat_1', array(
  'default'        => 'uncategorized',
  'capability'     => 'edit_theme_options',
));

Using this method, after we save something within the theme customizer, we can access it using get_theme_mod('cat_1');. In my front-page.php, here’s how I’m grabbing these customizations that you see in my example.

<?php
  $args = array(
    'category_name' => get_theme_mod('cat_1'),
    'posts_per_page' => 5
  );

  // Displays the category's name
  echo "<h3>" . get_category_by_slug($args['category_name'])->name . </h3>;
  $the_query = new WP_Query( $args );

  // The Loop
  if ( $the_query->have_posts() ) :
    echo "<ul>";
    while ( $the_query->have_posts() ) : $the_query->the_post();
      $link = get_permalink();
      $title = get_the_title();
      echo '<li><a href="' . $link . '">'  . $title . '</a></li>';
    endwhile;
    echo "</ul>";
  endif;

  // Reset Post Data
  wp_reset_postdata();

?>

There you have it, that’s how I did it! For your reference, here’s my full customizer.php

<?php

function get_categories_select() {
 $teh_cats = get_categories();
    $results;
    $count = count($teh_cats);
    for ($i=0; $i < $count; $i++) {
      if (isset($teh_cats[$i]))
        $results[$teh_cats[$i]->slug] = $teh_cats[$i]->name;
      else
        $count++;
    }
  return $results;
}

/**
 * Add postMessage support for site title and description for the Theme Customizer.
 *
 * @param WP_Customize_Manager $wp_customize Theme Customizer object.
 */
function basic_bootstrap_customize_register( $wp_customize ) {
  $wp_customize->get_setting( 'blogname' )->transport         = 'postMessage';
  $wp_customize->get_setting( 'blogdescription' )->transport  = 'postMessage';
  $wp_customize->get_setting( 'header_textcolor' )->transport = 'postMessage';

  $wp_customize->add_section('mytheme_options', array(
    'title'    => __('Front Page Categories', 'basicbs'),
    'priority' => 120,
  ));

  $wp_customize->add_setting('cat_1', array(
    'default'        => 'uncategorized',
    'capability'     => 'edit_theme_options',
  ));
  $wp_customize->add_control( 'cat_1', array(
    'settings' => 'cat_1',
    'label'   => 'Left Box',
    'section' => 'mytheme_options',
    'type'    => 'select',
    'choices' => get_categories_select()
  ));

  $wp_customize->add_setting('cat_2', array(
    'default'        => 'uncategorized',
    'capability'     => 'edit_theme_options',
  ));
  $wp_customize->add_control( 'cat_2', array(
    'settings' => 'cat_2',
    'label'   => 'Center Box',
    'section' => 'mytheme_options',
    'type'    => 'select',
    'choices' => get_categories_select()
  ));

  $wp_customize->add_setting('cat_3', array(
    'default'        => 'uncategorized',
    'capability'     => 'edit_theme_options',
  ));
  $wp_customize->add_control( 'cat_3', array(
    'settings' => 'cat_3',
    'label'   => 'Right Box',
    'section' => 'mytheme_options',
    'type'    => 'select',
    'choices' => get_categories_select()
  ));

}
add_action( 'customize_register', 'basic_bootstrap_customize_register' );

/**
 * Binds JS handlers to make Theme Customizer preview reload changes asynchronously.
 */
function basic_bootstrap_customize_preview_js() {
  wp_enqueue_script( 'basic_bootstrap_customizer', get_template_directory_uri() . '/js/customizer.js', array( 'customize-preview' ), '20130508', true );
}
add_action( 'customize_preview_init', 'basic_bootstrap_customize_preview_js' );

2 Replies to “Adding a select box with categories into WordPress’ theme customizer”

  1. Hello
    This made my day, But at a point i’m stuck. I am trying to use this with custom post type. it is working fine to wordpress post, but not showing any category name or content with custom post, like I am using to do this with ‘Games’ post type and ‘PC’, ‘Xbox’, ‘PS4’,..etc…. post category. I can find the category list in the customize but can’t see any output in the front page. Please help.

What do you think?