Create a category dropdown in WordPress customizer

Published January 8, 2021; last updated on September 10, 2021
Create a category dropdown in WordPress customizer

Whether you’re building a WordPress theme or a WordPress plugin, chances are that you need your users to select a certain category or multiple categories. For example, to apply some functionality or use different styling. You could do this via the WordPress customizer or, for example, in your own admin panel.

In this tutorial I’ll show you how to get a list of all the categories and how to rewrite that list to the format you need.

Get a list of all the categories

WordPress has a function called get_categories() (page in Codex). This function returns an array with WP_term objects and information about each category. We’ll retrieve a list of the categories and store them in a variable:

$rjs_categories_full_list = get_categories( array( 'orderby' => 'name', ) );

I used this small parameter orderby so that it’s ordered by name. You could also use array( 'orderby' => 'parent', ), which orders the whole thing according to the categories’ organisation.

This gives us the following output to work with:

array(4) { 
	[0]=> object(WP_Term)#525 (16) { 
		["term_id"]=> int(4) 
		["name"]=> string(14) "Child category" 
		["slug"]=> string(5) "child" 
		["term_group"]=> int(0) 
		["term_taxonomy_id"]=> int(4) 
		["taxonomy"]=> string(8) "category" 
		["description"]=> string(38) "Child category of the parent category." 
		["parent"]=> int(3) 
		["count"]=> int(1) 
		["filter"]=> string(3) "raw" 
		["cat_ID"]=> int(4) 
		["category_count"]=> int(1) 
		["category_description"]=> string(38) "Child category of the parent 		category." 
		["cat_name"]=> string(14) "Child category" 
		["category_nicename"]=> string(5) "child" 
		["category_parent"]=> int(3) 
	[1]=> object(WP_Term)#526 (16) { 
		["term_id"]=> int(3) 
		["name"]=> string(15) "Parent category" 
		["slug"]=> string(6) "parent" 
		["term_group"]=> int(0) 
		["term_taxonomy_id"]=> int(3) 
		["taxonomy"]=> string(8) "category" 
		["description"]=> string(42) "Cool category with another child category."
		["parent"]=> int(0) 
		["count"]=> int(1) 
		["filter"]=> string(3) "raw" 
		["cat_ID"]=> int(3) 
		["category_count"]=> int(1) 
		["category_description"]=> string(42) "Cool category with another child category." 
		["cat_name"]=> string(15) "Parent category" 
		["category_nicename"]=> string(6) "parent" 
		["category_parent"]=> int(0) 
	[2]=> object(WP_Term)#527 (16) { 
		["term_id"]=> int(2) 

Arguments of get_categories()

On the page in the Codex about the WordPress get_categories() function, you’ll not find an extensive list of parameters. The reason for this is that the get_categories() function makes use of the WP_Term_Query::__construct() constructor. This constructor ‘constructs’ the list of categories outputted by get_categories(). Therefore, you can pass the same arguments to get_categories() as to the WP_Term_Query::__construct(). See the Codex page about the WP_Term_Query constructor for all the arguments.

Rewriting the category list to the correct format

We need to use the output of the get_categories() to create a control in the customizer. To create a select control or a similar control, we need to provide the choices in this format:

'choices' => [
	'uncategorized' => 'Uncategorized', //In most cases this will be the default
	'category_slug' => 'Category name',

To rewrite our get_categories() result to the format required by 'choices', we’ll use a foreach loop.

	//Create an empty array
$rjs_choices_list = [];

	//Loop through the array and add the correct values every time
foreach( $rjs_categories_full_list as $rjs_single_cat ) {
	$rjs_choices_list[$rjs_single_cat->slug] = esc_html__( $rjs_single_cat->name, 'text-domain' );

We isolate each [x]=> object(WP_Term)#527 (16) {} with a foreach loop and store the information in a variable called $rjs_single_cat. We’ll add a new 'key' => 'value' pair to the $rjs_choices_list variable.

Every time, we use the slug as the key and the name as the value (and, just to be sure, strip it of invalid characters). We do this for each object(WP_Term). As it is not possible to have a duplicate slug, we’ll also never overwrite an other category by accident.

Create a category dropdown in the customizer

Let’s now add a dropdown control. We’ll use the default WordPress Customizer API, but you could use also the Kirki Customizer Framework, which is what I would recommend. If you would like to get started with Kirki, you should check out my Kirki beginners tutorial, where I’ll explain everything that’s needed to get started.

The default WordPress dropdown or select field.
The default WordPress dropdown.

Let’s create this dropdown or 'select' field. We’ll first put everything in a function and hook that to the 'customize_register' action. After that, we placed our category list code.

function rjs_customize_register( $wp_customize ) {

	//Get an array with the category list
$rjs_categories_full_list = get_categories(array( 'orderby' => 'name', ));

	//Create an empty array
$rjs_choices_list = [];

	//Loop through the array and add the correct values every time
foreach( $rjs_categories_full_list as $rjs_single_cat ) {
	$rjs_choices_list[$rjs_single_cat->slug] = esc_html__( $rjs_single_cat->name, 'text-domain' );

	//Register the setting
$wp_customize->add_setting( 'rjs_category_dropdown', array(
	'type'       => 'theme_mod', 
	'capability' => 'edit_theme_options',
	'default' => 'uncategorized',
) );

	//Register the control
$wp_customize->add_control( 'rjs_category_dropdown', array(
	'type' => 'select',
	'section' => 'rjs_category_dropdown', 
	'label' => __( 'Select category' ),
	'description' => __( 'Description.' ),
	'choices' => $rjs_choices_list, //Add the list with options
) ); 


add_action( 'customize_register', 'rjs_customize_register' );

You can retrieve the selected category with the get_theme_mod() function. The first parameter is the setting id and the second is the default value.

$category = get_theme_mod( 'rjs_category_dropdown', 'Uncategorized');
Selecting a category from the WordPress customizer.
Here you see the WordPress category dropdown in action.

Category dropdown with the number of posts

The above is of course great. We can still make it a little more refined by adding the number of posts in a certain category behind the category name. To accomplish that, we’ll need to make a small change to the foreach loop.

foreach( $rjs_categories_full_list as $rjs_single_cat ) {
    $rjs_category_name = $rjs_single_cat->name; 		//Retrieve the name
    $rjs_category_post_count = $rjs_single_cat->count; 	//Retrieve the count

	$rjs_choices_list[$rjs_single_cat->slug] = esc_html__( "{$rjs_category_name} ({$rjs_category_post_count})", 'text-domain' ); 

	//Note: don't forget the double quotes when concatenating the name, otherwise it will not work.

Which results in this:

The category select field from the WordPress customizer.
The category dropdown with the post count.

Wrapping up

As you see, creating a category dropdown in the WordPress customizer is incredibly easy. This technique for getting and rewriting a list of category information can also be applied in other cases. And there are many ways to expand on this, for example by creating a radio button.

Creating a category radio button in the WordPress customizer
Using the same technique to create a category radio button.

If you’ve any questions about this, feel free to leave a comment or e-mail me!

Stay up to date with all things Laravel, Tailwind, WordPress & PHP

Subscribe now to my e-mail newsletter and get my latest articles and project updates delivered directly to your inbox. Never miss an update.

Image Ralph J. Smit
Ralph is a designer gone developer. He happily lives in the Netherlands. His passion for good design drove him towards development, because he felt that no-code tools were too limiting. On this blog, Ralph writes the articles he would've wanted to have during his continual developer journey. → Follow on Twitter


Leave a reply

Your email address will not be published. Required fields are marked *

Do you want more articles like this delivered straight to your inbox?

Subscribe now to my e-mail newsletter and get my latest articles and project updates delivered directly to your inbox. Never miss an update.