0

By constant options I mean properties of the theme that don't change during every day use in production, but are changeable by the developer primarily for reusability purposes. Things like custom posts, sidebars, forms, custom features, etc.

There's really two ways that I see as viable and both of them are used in WordPress core and base themes. Edit: added a third way

Arguments inside functions

This is the way that I've been using for custom posts and such, and also the method WordPress uses for defining defaults for functions that take arguments, like wp_login_form() or wp_nav_menu(). It's either a variable defined inside the function being hooked or the values defined right inside the function call.

add_action( 'init', 'register_my_post_type' );

function register_my_post_type() {
    $labels = array(
        'name' => __( 'my_post_type' ),
        'singular_name' => __( 'My Post Type' ),
        ...
    );

    $args = array(
        'labels' => $labels,
        'public' => true,
        ...
    );

    register_post_type( 'my_post_type', $args );
}

Globals

The register_{anything} works by adding an instance to the global scope. For instance

function register_post_type( $post_type, $args = array() ) {
    global $wp_post_types;
    ...
    // validation
 
    $post_type_object = new WP_Post_Type( $post_type, $args );
    ...
    $wp_post_types[ $post_type ] = $post_type_object;

Constants

The most obvious example of this is the settings in wp-config.php. WordPress uses these for mostly small and really basic definitions, such as the database configuration credentials and things like
define( 'ABSPATH', __DIR__ . '/' ); or define( 'WPINC', 'wp-includes' );.

PHP supports defining arrays as constants since 5.6, so it could be possible to define these arguments. I think it would be nice if many of these options could be set in a separate file for simplicity.

Other methods, such as static variables or singleton classes seem inefficient, so they're off the table, but I'm not sure about constants.

So, would using constants like

define( 'MY_OPTION1', array(
    'key' => 'value'
    ...
));

then using them like

add_action('init', 'my_function');

function my_function() {
    some_function_that_takes_args( MY_OPTION1 );
    ...
}

be a bad idea? If yes, what is the correct/better way?

I have an impression that using constants might be a bad idea, though I'm not sure why or how bad. So what are some considerations in performance, usability, anomalies or other coding principles to consider?

2 Answers 2

1

Generally you should try to keep the amount of global variables/constants to a minimum. The third (constant) option might be a good idea if you don't have too many options, but it can get messy with time as you add more and more options.

What I usually do, is scope the constant to the corresponding classes as const or methods returning the settings values. For example, if I have a custom post type called Book, I would create a class that takes care of all the related functionality, such as registering the post type. Additionally all theme classes can be namespaced to avoid class name collisions, but I'll show the example without namespacing for simplicity:

class BookPost{
  const POST_TYPE = 'book';
  
  public static function register(){
    register_post_type(self::POST_TYPE, array('labels' => self::get_labels()));
  }

  public static function get_labels(){
    return array(
      'name' => __('Book', 'MyTheme'),
      //...
    );
  }
}

Then you can call register from outside or inside of the class without worrying about the parameters, for example:

add_action( 'init', 'BookPost::register' );

and if you need to access the post type (or other args) from anywhere else in the code, you can just use:

BookPost::POST_TYPE;
BookPost::get_labels();

There are a couple of things to mention here:

  1. Since you can't use expressions (such as calling the __() method) in constants, you will have to use methods for retrieving the more dynamic values like label.
  2. Here I'm using static methods because this particular example doesn't require storing state, and also it's easier to call the methods statically. But of course, based on your requirements you might prefer instantiating an object and using standard non-static methods.

I'm not saying that this is the best approach, but this is what I usually do and it's been working well for me. The additional advantage is that you can add more helper methods to this class as your code grows and you won't need to worry about passing the post type, etc. For example, you can have something like:

BookPost::get_latest();
BookPost::get_all();
BookPost::get_by_genre();

Also in terms of performance, registering a constant in a class vs using an array constant with options shouldn't make any meaningful difference in scenarios like this one.

2
  • So if I hook it to let's say 'init' this means that it gets instantiated on every pageload, just like if I used a globally defined function as a callback, right? Mar 2, 2022 at 11:07
  • @zoltankundi That's correct, add_action( 'init', 'BookPost::register' ); will run in the same way as add_action( 'init', 'register_my_post_type' );
    – Ben
    Mar 3, 2022 at 7:08
0

You should look at wordpress options page:

https://codex.wordpress.org/Creating_Options_Pages

That page will give you a good starting point to make options and settings for WordPres.

2
  • My question wasn't about this, but got me thinking. Every register_{something} function works by adding them to the global scope. So maybe creating globals is not out of question either. Jan 30, 2022 at 13:33
  • I edited the question and added global as an option. Jan 30, 2022 at 14:00

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.