The WordPress Customizer — which started out as the theme customizer — is currently one of the best options to allow end-users to customize a theme or plugin. The Customizer is rapidly expanding in its feature set, with the new panels in WordPress 4.0 and the work on a complete JavaScript API for the Customizer giving it a better overall UX and making it more useful.
Just as the Customizer doesn’t have to be limited to admin use only, it turns out that it doesn’t have to be limited in the use of setting options either. By default, the Customizer stores in theme mods — the special set of options for the current theme. It can also save to any other option.
In this article I’ll show you how to store the option in a different way, for example user meta. Once you understand how this works, you should be able to use the Customizer with any type of data storage. In fact, since we will be using a action hook, you will be able to use values set to cause any code to run.
Understanding alternative storage
When you add a setting to the Customizer, there is an argument called type. Normally this is where you set theme_mod or option. If the type is set to one of those two methods, then in the method that handles saving via Customizer, WP_Customize_setting::update(), you’ll find a switch that routes saving to them.
If neither of those values are set, it causes an action, customize_save_, to run, where the name is dynamically generated using that value. For example, if you set ‘josh’ as the value for type, then it will cause the action customize_save_josh to run.
This action will pass the value to save, and the WP_Customize_Setting class instance as params. The WP_Customize_Setting instance has a property called Id, which has the name of the option being saved.
Practical application: saving user meta
As an example of how to pull this together, I’ll walk you through how to save options to user meta. The first step is to create the setting. I’m assuming you know how to do this. If not, check out Sam (Otto) Wood’s excellent articles on the theme Customizer. Also, check out David Wood’s example code from his WordCamp Orlando 2014 talk on the Customizer.
The first thing you will need to do is create (or modify) a setting to have a custom storage type. Here’s an example from my original proof of concept that I hacked into Twenty Fifteen to modify the sidebar_textcolor option to use a custom storage type:
<?php $wp_customize->add_setting( 'sidebar_textcolor', array( 'default' => '#fff', 'sanitize_callback' => 'sanitize_hex_color', 'transport' => 'postMessage', 'type' => 'user_meta' ) );
As I explained above, updating this setting will cause the action customize_save_user_meta to fire, which we can then hook to, in order to do the saving. The callback function for this action is very simple. It is one line, using update_user_meta() to save the value into the current user’s meta.
In order for update_user_meta() to work, we need a user ID, the key name, and the value. We can get the user ID from get_current_user_id(), the key from the class instance — as described above — and the value to save from the first parameter passed by the action. Here’s what it looks like:
<?php /** * Handle saving of settings with "user_meta" storage type. * * @param string $value Value being saved * @param WP_Customize_Setting|onj $WP_Customize_Setting The WP_Customize_Setting instance when saving is happening. */ add_action( 'customize_update_user_meta', function( $value, $WP_Customize_Setting ) { update_user_meta( get_current_user_id(), $WP_Customize_Setting->id, $value ); }, 10, 2 );
Getting the value
In this example, it’s unsafe to assume that the user meta key for the option will be set for the current user. Therefore you will need to create a function to get the user’s setting, and fallback to the site default if the current user has not set a value for this setting.
There are lots of ways to do this, but I wrote a simple function to illustrate how to first check if the current user has saved a value for a setting, and if not use the option of the same name. Be careful with this because, because depending on what type of setting you are working with, the way the data is returned will vary.
My example code is from my proof of concept, which stored a simple string. The tricky part is that get_user_meta returns an array, the first index of which has the value we need, but, when get_option is used, a simple string is returned. That’s why I built in a conditional check to convert the array from get_user_meta() to the string I need. You must be careful and test in advance, as the type of data you’re saving and the storage method you use will change your needs.
<?php /** * Function to get a user's option, or a theme_mod if they don't have one set. * * @params string $key Option to get */ function slug_user_option_or_theme_option( $key ) { if ( false !== ( $value = get_user_meta( get_current_user_id(), $key, true ) ) ) { $value = get_option( $key ); }else { if ( is_array( $value ) ) { reset( $value ); $value = $key( $value ); } } return $value; }
Taking it further
What we haven’t discussed yet is how the admin user sets the site default using theme_mods or option storage types the standard way. Because settings can be added to the Customizer based on the current user’s capability, this means that you could add two settings.
One setting would only available if the current user’s capability includes update_options, which would save to theme_mods. This would establish the site default. The other setting will be available to all other users, which saves to user_meta as I described above. Because controls and settings are separate in The Customizer API, you can use the same control for both settings.
What else can you do?
Realizing that the customize_save_ hook is available opens up a lot of interesting possibilities. For example, something very similar to what I highlighted above could be employed to use the Customizer to set site options for multi-site, like so:
<?php /** * Handle saving of settings with "user_meta" storage type. * * @param string $value Value being saved * @param WP_Customize_Setting|onj $WP_Customize_Setting The WP_Customize_Setting instance when saving is happening. */ add_action( 'customize_update_site_option', function( $value, $WP_Customize_Setting ) { update_site_option( $WP_Customize_Setting->id, $value ); }, 10, 2 );
Of course, you are not limited to using this technique for saving data. That action hook can be used to do anything. This is where your creativity comes into play. For example, you could use it to create a redirect, or trigger a popup on save if a certain setting is updated. This could be used to add extra confirmation or extra options.
10 Comments