This entry is part 7 of 7 in the Writing Your First WordPress Plugins, Basic to Advanced Series
- How to Begin Writing Your First WordPress plugin
- Structuring Your First WordPress Plugin
- Writing Your First WordPress Plugin Part 3
- Writing Your First WordPress Plugin Part 4
- Writing Your First WordPress Plugin Part 5
- Writing Your First WordPress Plugin Part 6
- Writing Your First WordPress Plugin Part 7 – Final
Part seven of Writing Your First WordPress Plugin concludes the series by demonstrating how to extend the plugin options that I showed you in part 6, and how to use them to control various aspects of your plugin’s output, such as turning it on or off and changing theoutput’s theme. There is not a lot of new material covered in this part, but a couple of key points are explained that will greatly assist you writing WordPress plugin option pages.
The first thing added to the plugin, is a checkbox in the options page to turn the output on or off. So rather than simply forcing our users to display the Twitter link, we give them an option of disabling it if they want. The following code in our “admin-page.php” file will add the necessary checkbox:
<input id="mfwp_settings[enable]" type="checkbox" name="mfwp_settings[enable]" value="1" checked="checked" /> <label class="description" for="mfwp_settings[enable]"><?php _e('Display the Follow Me on Twitter link', 'mfwp_domain'); ?></label> |
To me, it makes the most sense to place the checkbox just above the input field where we ask the user to enter their Twitter URL. Now, we must check whether the checkbox has been marked in our “display-functions.php” file. Doing so is simple, just add a second condition to our is_singular() conditional statement:
if(is_singular() && $mfwp_options['enable'] == true) { // . . .. } |
Your user now has the option to enable or disable the Follow Me on Twitter box completely.
Now, in order to provide our user a couple of options in terms of the plugin output’s appearance, we should add a select drop down menu that allows the user to choose the “theme” of the output. Doing so is simple. In our “admin-page.php” file place this, just below the Twitter URL input:
<?php $styles = array('blue', 'red'); ?> <select id="mfwp_settings[theme]" name="mfwp_settings[theme]"> <?php foreach($styles as $style) { ?> <?php if($mfwp_options['theme'] == $style) { $selected = 'selected="selected"'; } else { $selected = ''; } ?> <option selected="selected" value="<?php echo $style; ?>"><?php echo $style; ?></option> <?php } ?> </select> |
The logic behind this select menu is explained in the video, so I suggest watching it if you are confused by what is going on here. Your final plugin’s options page should look like this:
Next, since we have given the user a way to choose the theme, we need to output the selected theme in the plugin’s HTML. What we will do here is output the selected option as a CLASS in our paragraph tag. This is in “display-functions.php”:
$extra_content = ' |
Notice the $mfwp_options[‘theme’] after the “twitter-message” class name. The user’s chosen option will now be used as a class name, so now we can target it using plain and simple CSS, like so:
.twitter-message.blue { color: blue; border: 1px solid #ccc; } .twitter-message.red { color: red; border: 1px solid red; } |
And that does it! Your very first WordPress plugin is now complete!
To roundup, here are some of the important parts of writing WordPress plugins I have demonstrated in this series:
- Beginning your plugin
- Creating a organized and easy to read file structure
- Using WordPress Conditional Tags to control the output of your content
- Loading scripts and styles in WordPress plugins correctly
- Creating a plugin options page in your WordPress admin
- Creating different kinds of plugin options in your settings page
- Using your plugin’s options to control the output of your plugin
- . . . and how to write a WordPress plugin from start to finish
I hope you have found this series helpful, and I would really appreciate it if you would leave your feedback, comments, criticism, etc. If you enjoyed this series, and any of my other tutorials, and you’d like to see more like it, would you consider supporting the site?
If you’d like to test out the final plugin, or simply browse through its code, the download link is below.
Download Complete Plugin
Hi There, I watched all this serie, and I really learned a lot.
One note:
WP also have the selected() function just like checked(), you could use that on the tag
http://codex.wordpress.org/Function_Reference/selected
Awesome series! It touched on a lot of good stuff to get me started.
You are a natural!
I created 2 plugins that use the same javascript.
If I put a copy in each plugin folder, I have to maintain 2 copies (or more if I use it again)
So I put one instance of the javascript in plugin_url()/js/script.js and pointed both scripts to it and they worked fine.
But when I deleted one of the plugins and clicked βdelete all files associated with this plugin”, I lost the single version at plugin_url()/js/script.js .
Do you have a suggestion on how to approach this?
Thanks!
You should put the script in each plugin. It’s better to duplicate your script than break one of the plugins if the other is inactive π
@Pippin wouldn’t it be better to use a CDN or host the script somewhere online if the plugin is intended to be used for oneself? (assuming internet is not a problem)
Yes, CDNs are generally better.
I created a plugin with custom tables.
Creating tables at activation works fine.
However, I am trying to figure out when/how to delete tables at plugin “Deletion” time.
I added an uninstall.php file with the following content (but it doesn’t seem to execute). Not sure what I am doing wrong.
Thanks!
[code language=”php”]
if( ! defined( ‘WP_UNINSTALL_PLUGIN’ ) )
exit();
function gii_plugin_table_delete() {
global $wpdb;
$table_name = $wpdb->prefix . “comm_auth_calendar”;
$wpdb->query(“DROP TABLE IF EXISTS $table_name”);
$table_name = $wpdb->prefix . “comm_calendar_mssgs”;
$wpdb->query(“DROP TABLE IF EXISTS $table_name”);
}
add_action( ‘init’, ‘gii_plugin_table_delete’ );
[/code]
The “init” action doesn’t fire during the uninstall process, so remove the add_action() and just call gii_plugin_table_delete() directly in the uninstall.php file.
Thank you for the nice tutorial, very well structured and easy to grasp. It saved me a lot of time to familiarize myself with creating a WP plugin.
I would love to see a proper functioning reset button added to the options page. Any good tutorial around?
For resetting plugin options to default?
Yes, nice and safe way for resetting options to default.
Do you know how to whitelist the default options? Once you’ve done that, all you need to do is simply delete the stored options from the database and the whitelist will become the default again.
For whitelist we just need to make a call to register_setting() right? So it means I just need to make a call to delete_option() when someone hits the reset button?
Yes.
Ok, thanks π
As I look at other people’s plugins I notice several of them test for admin privilege at activation and deactivation with something like this:
if ( ! current_user_can( ‘activate_plugins’ ) )
return;
Is this redundant since plugin option is only available to admins thru the dashboard or good practice i.e. “security in layers”? . . . or other?
Thanks!
It’s not entirely redundant, since it would be possible for other plugins to provide a means to activate a plugin by a non-admin, but in general I’d say it’s unnecessary. Instead, I would make sure that the individual features within the plugin that need to be restricted to certain user roles have the proper capability checks.
I love your tutorial, but…for some reason I’m not getting the settings into WordPress.
Okay…. I dug around a bit and I’m currently stuck.
When I put the plugin on my system, I get…
ERROR: options page not found.
I’m not able to access options.php with the form action method=”post”.
Hmmm. Any suggestions?
Could you post your complete code to pastebin.com then share the link?
I was going to say, the code is the same as your sample plugin….then my developer hat came out and I decided to make sure.
I found the problem.
I missed a couple of the mfwp_ prefixes that caused the failure.
So, I look a little foolish, but not totally stupid (I hope)?
Sorry for the noise.
Thanks for the great tutorial!
Hi Pippin,
Great work. I’ve been through this series three times as I’ve started to learn how to write plugins. Thank you.
One thing I’ve noticed is that I’m getting an error for line 17 in the admin-page.php.
I thought it was just an error in my code as I copied along with you in the video, but it turns out that even when I downloaded and overwrite my files with your plugin files I get the same error.
Would you activate and try out this plugin to see if you get the same error?
Error:
Notice: Undefined index: enable in **my folders here**\wp-content\plugins\my-first-wordpress-plugin\includes\admin-page.php on line 17 />
Thanks!
Can you show me line 17?
Sure thing. Thank you Pippin. Just to be sure I uninstalled the plugin and reinstalled again with your files from the full plugin link above.
Line 17:
<input id="mfwp_settings[enable]" name="mfwp_settings[enable]" type="checkbox" value="1" />
I get that error when the Enable checkbox is deselected. When I enable and save it, the above Notice: error message in the Settings>My First Plugin goes away.
The post view on disabled also gives and error instead of removing the text and link. It reads:
Notice: Undefined index: enable in C:\**my folders here**\wp-content\plugins\my-first-wordpress-plugin\includes\display-functions.php on line 9
So here’s line 9 in display-funciton.php:
if(is_singular() && $mfwp_options[‘enable’] == true) {
If it helps, I’m using a local install of WP and I’m on version 3.9.1 running Twenty Thirteen theme.
Thx again Pippin
It’s probably caused by the checked() function. Wrap the $options[‘enabled’] part in isset( $options[‘enabled’] )
TaDa! Great. That worked!
I’m currious. Since your code obviously works in your video, is this an impact caused by the later versions of WordPress?
I wrapped it over the enabled option on line 9 in the display function.php and line 17 in the admin-page.php
For all the ‘new to coding’ persons like me:
I changed
$mfwp_options[‘enable’]
to
isset( $mfwp_options[‘enable’])
It was probably broken in mine too but simply wasn’t showing because I had debug display disabled.
Hi,
Great tutorial, all worked really well, and I now wrote my own Google Adsense plugin basing on your code (as I couldn’t find one that works the way I wanted… π )
Question though:
Is there a way of executing plugins in a particular order? I mean adding more and more strings to the displayed content in a controlled manner?
I want some content from a third party plugin to be displayed before my own plugin, but at the moment it is displayed after my code…
Cheers,
M.
No really great way. WordPress executes plugins in alphabetical order.
Really great tutorial Pippin. Easy to follow, understand an everything was explained nicely. I’ve been trying to do web design but I’m just not really a designer, so i’m trying my hand at plugins and it’s tutorials like this that make learning something new sooo much easier.
Thank you and God Bless!
Hi Pippin,
When WP_DEBUG enabled, checkbox gives “Notice: Undefined index: enable” error.
You can fix that by using the isset() function to check if the “enable” key is present in the options array.
Thanks Pippin, // // works.
Thanks Pippin, // isset($url_options[‘enable’]) && checked(1, $url_options[‘enable’]); // works.
Thanks Pippin for awesome tutorial.
Everything worked just like you said.
What I have done is added another checkbox and textarea after content,
but how do i get it to show added content when checked and other twitter url content is unchecked or both are checked or vice versa?
i’ve tried if, if else and other things. Even tried writing separate function too.
newbie, hope i explained what i’m trying to do.
Did you modify the part of the plugin that displays the content?
no i just added it to add_content plugin. to the if single and mfp_options = true && mfp_more content == true and then added a variable for more_content.
or add_content function I mean…
Can you show me your complete plugin?
yes sir, same as yours just added to it;
if (is_single() && $mfp_options[‘enable’] == true && $mfp_options[‘more_content’] == true) {
$extra_content = ‘ Follow me on Twitter ‘;
$more_content = $mfp_options[‘more_content’];
$content .= $extra_content .= $more_content;
}
return $content;
}
yes sir,
if (is_single() && $mfp_options['enable'] == true && $mfp_options['more_content'] == true) {
$extra_content = ' Follow me on Twitter ';
$more_content = $mfp_options['more_content'];
$content .= $extra_content .= $more_content;
}
return $content;
}
yes sir,
been trying to post code, but doesn’t happen. Don’t have it live yet, just on localhost.
<!– if (is_single() && $mfp_options['enable'] == true && $mfp_options['more_content'] == true) {
$extra_content = ' Follow me on Twitter ‘;
$more_content = $mfp_options[‘more_content’];
$content .= $extra_content .= $more_content;
}
return $content;
} –>
Been trying to post code on here but not sure how. Like I said newbie. Maybe need to try and figure it out, my bad.
Thanks Pippin, will email back when registered for your advanced stuff.
if (is_single() && $mfp_options[‘enable’] == true && $mfp_options[‘more_content’] == true) {
$extra_content = ‘ Follow me on Twitter ‘;
$more_content = $mfp_options[‘more_content’];
$content .= $extra_content .= $more_content;
}
return $content;
}
[code language=”php”]
function mfp_add_content($content) {
global $mfp_options;
if (is_single() && $mfp_options[‘enable’] == true && $mfp_options[‘more_content’] == true) {
$extra_content = ‘ Follow me on Twitter ‘;
$more_content = $mfp_options[‘more_content’];
$content .= $extra_content .= $more_content;
}
return $content;
}
[/code]
Do you have a tutorial on sanitizing the data?
Take a look at this page on the WP codex: http://codex.wordpress.org/Data_Validation
<?php
/* for displaying stuff */
function mfp_add_content($content) {
global $mfp_options;
if (is_single() && $mfp_options['enable'] == true && $mfp_options['more_content'] == true) {
$extra_content = ' Follow me on Twitter ';
$more_content = $mfp_options['more_content'];
$content .= $extra_content .= $more_content;
}
return $content;
}
I’ve posted code example on stackoverflow.
http://stackoverflow.com/questions/26469669/adding-checkboxes-to-admin-panel-in-wordpress
Can you show me the complete plugin?
Yes Pippin, just put it up on github:
https://github.com/JustBend/MyFirstPlugin.git
Ok I’m a little unclear. To help me help you, could you explain exactly what you want your plugin to do and exactly what it is (or is not) doing right now?
I’ve added another checkbox and textarea after content,
but how do i get it to show added content when checked?
When other twitter url content is unchecked or both are checked or vice versa.
it shows both unless twitter url is unchecked then shows neither…
I can even add more_content in other places or pages with
$mfp_options[‘more_content’]
but still shows up whether checked or unchecked in admin page.
thanks again for all your help…
Is this right?
One checkbox should enable / disable Twitter.
One checkbox should enable / disable the extra content field.
Yes sir, and thanks again.
Great stuff, Pippin! This series is a great way to get my feet wet. What do you suggest for the “next step” of learning about writing plugins?
Thanks for this series!
I’d suggest checking out my Plugin Development 101 series. It goes into more depth: https://pippinsplugins.com/series/plugin-development-101/
Thanks Pippin for a great tutorial. The videos were a real help. Looking forward to expnding on this to create a new plugin from scratch.
don’t want anything to do with you anymore!
With me Steve? If I’ve offended you in some way, I’m sincerely apologetic and that is never my intent.
I think a thread got mixed up here as I am more than happy with things here
Glad to hear it David π
I followed the entire series. Truly fantastic.
I’m attempting to create a plugin that allows for the entry of employees. Looking to have name, job title, twitter username, etc. entered in via a form. My question is how do I allow for this data to be entered, saved, then the addition of a new one? I’ve tried searching this out a bit, but I don’t really know what to call what I’m doing. Any guidance would be greatly appreciated.
I would suggest registering a custom post type.
Hey Pippin,
This is a great tutorial and I have started to recode my plugin with the structure you have taught. My question is, how do I get the value of the twitter url into another file within the plugin?
I have the following:
But it doesn’t return the value of the field. It’s an XML file that also pulls meta from a custom post type.
Any suggestions?
Thanks again!
Could you show me the code you’re using again? Looks like it got stripped out of the comment.
Hi,
thank you for all of this, I learn a lot of this series.
Thanks you very much. God bless and keep up π
Excellent video tutorial..
Thanks for this series Pippin, I’ve learned a lot.
This last video (episode 7) doesn’t seem to allow full screen.
Hard to see your code.
Cheers,
Hacker (Berry NSW Australia)
Hmm, that’s very strange. If you watch it on YouTube, you can go fullscreen: https://www.youtube.com/watch?v=A_-Bp5JSN6U
First of all thanks for such a great tutorial, i have few queries.
1) Is that compulsory to put “for” attribute in label tag as i think its only for display ?
2) Is there any kind of data validation (Server side) we need to put on fields in backend or its just fine as we are in wordpress administration panel ?
Thank You Very Much !!
1. The for attribute connects the label to the input field, making it so that when the label is clicked on, the input field receives cursor focus.
2. You should always validate the data submitted. Anytime you’re processing form input, it’s best to assume the data cannot be trusted.
Firstly, thanks for a great tutorial!
I have built a plugin to create a CPT and taxonomies.
I am using my options page to allow users to change the permalink structure of the CPT and taxonomies and it is working great! Is it possible to flush the rewrite rules when the options are updated instead of telling users to go to settings>permalinks?
Yes it is! You can use this function for that: https://codex.wordpress.org/Function_Reference/flush_rewrite_rules
Great thanks. I added the following and it seems to be working fine:
// Flush rewrite rules on saving
add_action( ‘init’, ‘gcsp_flush_rewrite_on_save’ );
function gcsp_flush_rewrite_on_save() {
if ( isset( $_REQUEST[‘settings-updated’] ) ) {
flush_rewrite_rules();
}
}
Is that the way you would do it, or is there a better way….?
You will need to add some additional checks to make sure that only runs when your plugin’s settings are saved, otherwise they permalinks will be flushed anytime any settings are saved.
Hmm ok so i’ve scrapped that!
I have instead added a callback to the admin_init function:
add_action(‘admin_init’, ‘gcsp_register_settings’);
function gcsp_register_settings() {
// creates our settings in the options table
register_setting(‘gcsp_settings_group’, ‘gcsp_settings’, ‘gcsp_set_rewrite_flag’);
}
function gcsp_set_rewrite_flag( $gcsp_settings ) {
add_option( ‘gcsp_flush_rewrite_rules_flag’, true );
return $gcsp_settings;
}
The option i am adding is checked in my main plugin file to flush the permalinks:
// Flush rewrite rules if the previously added flag exists, and then remove the flag
add_action( ‘init’, ‘gcsp_flush_rewrite_rules’, 99 ); // after cpt has registered
function gcsp_flush_rewrite_rules() {
if ( get_option( ‘gcsp_flush_rewrite_rules_flag’ ) ) {
flush_rewrite_rules();
delete_option( ‘gcsp_flush_rewrite_rules_flag’ );
}
}
I also use this function on my register_activation_hook to flush permalinks when my plugin activates – Is it ok to do it like this?