115

You can make the 'slug' for the submenu page equal that of the top level page, and they'll point to the same place: add_action('admin_menu', 'my_menu_pages'); function my_menu_pages(){ add_menu_page('My Page Title', 'My Menu Title', 'manage_options', 'my-menu', 'my_menu_output' ); add_submenu_page('my-menu', 'Submenu Page Title', 'Whatever You Want',...


90

Okay, I've had two big projects where I've been in control of the server enough to namespace and rely on autoloading. First up. Autoloading is awesome. Not worrying about requires is a relatively good thing. Here's a loader I've been using on a few projects. Checks to make sure the class is in the current namespace first, then bails if not. From there it'...


88

Coming in late to this party, but here's the "WordPress" way: use plugin_dir_path( __FILE__ ), e.g.: <?php include( plugin_dir_path( __FILE__ ) . 'ipn/paypal-ipn.php'); ?> Note that the function does return the trailing slash for the filepath.


79

Arriving here exactly 2 years after the original question was asked, there are a few things I want to point out. (Don't ask me to point out a lot of things, ever). Proper hook To instantiate a plugin class, the proper hook should be used. There isn't a general rule for which it is, because it depends on what the class does. Using a very early hook like "...


74

I would start with this question: Is the functionality related to presentation of content, or with generation/management of content, or of the site, or of the user identity? If the functionality is not related specifically to presentation of content, then it is squarely within Plugin Territory. This list is long: Modifying core WP filters (wp_head content, ...


65

To add our button to the TinyMCE editor we need to do several things: Add our button to the toolbar Register a TinyMCE plugin Create that TinyMCE plug-in which tells TinyMCE what to do when our button is clicked. Steps #1 and #2 In these steps we register our TinyMCE plug-in which will live inside a javascript file at 'path/to/shortcode.js' (see ...


60

Good question, there are a number of approaches and it depends on what you want to achieve. I often do; add_action( 'plugins_loaded', array( 'someClassy', 'init' )); class someClassy { public static function init() { $class = __CLASS__; new $class; } public function __construct() { //construct what you see fit here....


59

You should be skeptical of anyone who says that there is a single "right" way. The right way depends on the situation. Using the CPT infrastructure has a number of notable benefits: You get the Dashboard UI for free You automatically take advantage of WP's caching, including any persistent cache plugins that the installation may be using You automatically ...


56

When you visit a frontend page, WordPress will query the database and if your page does not exist in the database, that query is not needed and is just a waste of resources. Luckily, WordPress offers a way to handle frontend requests in a custom way. That is done thanks to the 'do_parse_request' filter. Returning false on that hook, you will be able to ...


51

An easy test where the code is best placed: write the code into the functions.php switch theme do you miss the functionality, is the blog not proper working or fragments of the old theme (e.g. shortcodes) are left? yes: put it into a plugin no: leave it in functions.php Examples: Write a shortcode. After switching the theme, the plain shortcodes are left ...


48

I think you have to be a little careful because it depends on what you are trying to do. If you are using a child theme get_template_directory(); will still go to the parent theme. However get_stylesheet_directory(); will go to the current theme, child or parent. Also, both these functions return absolute server paths. If you wanted a fully formed URI, ...


48

In backend there is global ajaxurl variable defined by WordPress itself. This variable is not created by WP in frontend. It means that if you want to use AJAX calls in frontend, then you have to define such variable by yourself. Good way to do this is to use wp_localize_script. Let's assume your AJAX calls are in my-ajax-script.js file, then add ...


38

1. Write with localization in mind Don't use echo or print() to produce text output, instead use the WordPress functions __() and _e(): /** Not localization friendly */ echo "Welcome to my plugin"; // OR print("Welcome to my plugin"); /** Localization friendly */ _e('Welcome to my plugin', 'my-plugin'); // OR $my_text = __('Welcome to my plugin', 'my-...


36

As far WordPress is concerned - your multi-dimensional array is one option. To update just part of the multi-dimensional array its necessary to retrieve the entire array, alter it accordingly and then update the entire array. Suppose your multi-dimensional array is as follows: my_options = array( 'option_a'=>'value_a', 'option_b'=>'value_b', '...


35

Thanks for the answers guys. Though both answers set me on the right path, none worked out of the box. So I'm sharing my solutions below. Method 1 - Using register_activation_hook: Create the Parent Plugin in plugins/parent-plugin/parent-plugin.php: <?php /* Plugin Name: Parent Plugin Description: Demo plugin with a dependent child plugin. Version: 1.0....


34

Whenever you find a piece of code without clear installation instructions it is probably a plugin. The example you gave is a good one, because that is the most common case: add_action('template_redirect', 'remove_404_redirect', 1); function remove_404_redirect() { // do something } To use such a snippet, put it into a plugin: Create a new file, name it ...


33

You can use the remove_action() function, like this: remove_action('publish_post', 'old_action'); add_action('publish_post', 'new_action'); It's important to note that if the old_action was added with a priority parameter, you must add that to the remove_action call, otherwise it will fail to remove it. There are other implications if the old_action was ...


33

to use ajaxurl directly, in your plugin file add this: add_action('wp_head', 'myplugin_ajaxurl'); function myplugin_ajaxurl() { echo '<script type="text/javascript"> var ajaxurl = "' . admin_url('admin-ajax.php') . '"; </script>'; } you can then use the ajaxurl for ajax request.


32

Short answer: your name attribute values must use the schema option_name[array_key]. So, when you use … <input name="option_name[key1]"> <input name="option_name[key2]"> … you get an array as option value in your validation function: array ( 'key1' => 'some value', 'key2' => 'some other value' ) PHP does that for you, this is ...


32

There are many themes and plugins using jQuery as loaded by WP core. Every time jQuery is updated, there is a risk of older themes and plugins breaking (because lots of them are still used but no longer updated). That's why you also see jquery-migrate.js in your source code. It's a script that catches old functions used by plugins/themes and makes sure that ...


31

As the error says you need an instance of the class to use $this. There are at least three possibilities: Make everything static class My_Plugin { private static $var = 'foo'; static function foo() { return self::$var; // never echo or print in a shortcode! } } add_shortcode( 'baztag', array( 'My_Plugin', 'foo' ) ); But that’s not ...


31

The default response from admin-ajax.php is, die( '0' ); ...by adding your own wp_die() or exit() or die() after returning your desired content prevents the default response from admin-ajax.php being returned as well. It also generally means that your ajax call has succeeded. Ultimately, to answer your question, it's meant to work this way. What you ...


30

The easiest way to do this is actually a combination of wp_enqueue_script and the footer actions that Saif and v0idless already referenced. I frequently use jQuery in my themes and plugins, but I put all of the other scripts in the footer as well. The best way to actually queue things up would be this: function myscript() { ?> <script type="text/...


30

The reason this doesn't work is because there is a redirection happening after the save_post action. One way you can acheive want you want is by implementing a quick work around using query vars. Here is a sample class to demonstrate: class My_Awesome_Plugin { public function __construct(){ add_action( 'save_post', array( $this, 'save_post' ) ); ...


28

Okay, I'll take a stab at this. Some limitations I encountered along the way: There are not a lot of filters in subclasses of WP_List_Table, at least no where we need them to be. Due to that lack of filters, we can't really maintain an accurate list of plugin types at the top. We also have to use some awesome (read: dirty) JavaScript hacks to display ...


28

Use get_posts() and the parameter name which is the slug: $page = get_posts( array( 'name' => 'your-slug' ) ); if ( $page ) { echo $page[0]->post_content; } Be aware that the post type in get_posts() defaults to 'post'. If you want a page use … $page = get_posts( array( 'name' => 'your-slug', 'post_type' => 'page' ...


28

Your code seems correct, but it will load the script only in admin area beacuse you are enqueuing the script in admin_enqueue_scripts action. To load the script in frontend, use wp_enqueue_scripts action (which is not the same that wp_enqueue_script() function): function Zumper_widget_enqueue_script() { wp_enqueue_script( 'my_custom_script', ...


27

AFAIK, there's no official/standard framework, and there will be as many plugin development styles as there are shades of white in north pole. I'd say WordPress Coding Standards is a blueprint for a good style. You'll find lots of good examples and excellent coders here in WPSE. A nice starting point: questions/tagged/plugin-development. Highlighting: ...


26

Use the Core API, not only its CSS Normally you just use an instance of the WP_List_Table class. Guides: More about it in the Codex here. Here's also a guide from WP Engineer - too much to copy it over. And another guide on Smashing Magazine online. Benefits? YES! You can add pagination, search boxes, actions and whatever magic you can imagine (and are ...


25

The API you offer in a plugin or a theme depends on the logic of that specific code. There is probably no guide that applies to all situations. I am a contributor for multiple plugins with APIs, and what I have learned so far is: Do not offer an API until you really know how people use your code. Release the first two or three versions without any API. ...


Only top voted, non community-wiki answers of a minimum length are eligible