People who code: we want your input. Take the Survey
84

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 "...


65

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 ...


65

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 ...


45

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....


45

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.


41

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 ...


36

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', ...


36

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 ...


35

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 ...


34

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' ) ); ...


31

Because you're using a namespace in this class, you need to add a \ in front of the WP_Query call to tell PHP that it's in the global namespace and not the namespace of this class. Try this: $query = new \WP_Query($args);


29

The most comprehensive method is get_current_screen added in WordPress 3.1 $screen = get_current_screen(); returns WP_Screen Object ( [action] => [base] => post [id] => post [is_network] => [is_user] => [parent_base] => edit [parent_file] => edit.php [post_type] => post [taxonomy] => )


29

When in doubt, look at the source code. Digging in to get_option(), you'll see (abbreviated): $value = wp_cache_get( $option, 'options' ); if ( false === $value ) { $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) ); // Has to be get_row instead of get_var because ...


29

First of all, WordPress registers jQuery UI via wp_default_scripts(). Dependencies are already set, so you only need to enqueue the script you really need (and not the core). Since you're not changing version number or anything, it is ok to only use the handle. // no need to enqueue -core, because dependancies are set wp_enqueue_script( 'jquery-ui-widget' ); ...


27

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. No ...


26

It is mandatory, though it is not enforced. Consider the scenario when two Wordpress site has been setup in the same database. One with prefix wp_ and another with wp2_. If you install your plugin in both of the sites with the prefix, your created tables will be wp_liveshoutbox for first site and wp2_liveshoutbox for the second site. But if you omit the ...


25

Do not point the URL to admin.php, use admin-post.php instead: '<a href="' . admin_url( 'admin-post.php?action=print.csv' ) . '">' In your plugin register a callback for that action: add_action( 'admin_post_print.csv', 'print_csv' ); function print_csv() { if ( ! current_user_can( 'manage_options' ) ) return; header('Content-Type: ...


24

The following small plugin creates a custom button inside line 1 of the WordPress TinyMCE Version 4, tested in WP Version 3.9-beta2. The plugin has var_dump included to understand the values. It's also possible to add the button to other lines of the visual editor, only a other hook, like for line 2: mce_buttons_2. Result Plugin, PHP side - tinymce4-test....


23

Best practice method Have a look at wp_localize_script, which is meant to do exactly that. But it does require previous usage of wp_enqueue_scripts, hence you will need to move your JS to a separate file indeed. It will be worth those few minutes of effort though, for sure. function wpse_96370_scripts() { if ( is_single() ) { ...


23

Maybe a little late but I stumbled on this when I was having issues figuring it out so thought I would supply what I found out for future people. I've found the basic principles are to have a hidden input named action and it's value being a custom set identifier. For example <input name='action' type="hidden" value='custom_form_submit'> With this ...


23

It's not outdated Moving to 2.x or 3.x is too early, people still use IE8 which is only supported on 1.x


22

They are defined as follows: define( 'ABSPATH', dirname(dirname(__FILE__)) . '/' ); define( 'WPINC', 'wp-includes' ); dirname is a PHP function that returns the path of the parent directory, and wp-includes is pretty self explanatory. I would say ABSPATH is better because it's one of the first things WP loads and it also looks better:) But there is no ...


21

Maybe using the wp_redirect() function in the activation hook. In the following example myplugin_settings is a placeholder. Normally this simply is the $hook_suffix you get back from $hook_suffix = add_menu_page( /* etc. */ ); and similar functions. THIS CODE DOESN'T WORK, READ BELOW register_activation_hook(__FILE__, 'cyb_activation'); function ...


21

Reference file in current path or deeper nested To reference the current path plugin_dir_path( __FILE__ )."further/nesting/here.css"; which works in Plugins and Themes. Reference URl/URi in a plugin To point to a plugin or theme file, use plugins_url( "path/to/file", __FILE__ ); which works only in plugins Reference URl/URi in wp-admin folder ...


21

"Error: Options Page Not Found" Bug This is a known issue in the WP Settings API. There was a ticket opened years ago, and it was marked as solved -- but the bug persists in the latest versions of WordPress. This is what the (now removed) Codex page said about this: The "Error: options page not found." problem (including a solution and explanation): ...


21

Here are some random thoughts on this: Question #1 How much money did we send to grandma? For 100 page loads, we sent her 100 x $1 = $100. Here we actually mean 100 x do_action( 'init' ) calls. It didn't matter that we added it twice with: add_action( 'init','send_money_to_grandma' ); add_action( 'init','send_money_to_grandma' ); because the ...


20

Here's a 2017 answer. Autoloading is awesome. Namespacing is awesome. Although you can roll it yourself, in 2017 it makes the most sense to use the magnificent and ubiquitous Composer to handle your PHP requirements. Composer supports both PSR-0 and PSR-4 autoloading, but the former has been deprecated since 2014, so use PSR-4. It reduces the complexity of ...


19

Your question is not really about WordPress, it is more about PHP and refactoring. But we see so much bad code here, and the pattern I will explain below (MVC) could help many other developers, so I decided to write a little answer. Keep in mind, there is a dedicated site for such questions in our network: Code Review. Unfortunately, very few WordPress ...


19

Maybe what you're looking for is : WP_PLUGIN_DIR // full path, no trailing slash WP_PLUGIN_URL // full url, no trailing slash See documentation


19

Before being printed, all the menu items get run through a filter. You can target the wp_nav_menu_items filter to tack things on to the menu: // Filter wp_nav_menu() to add additional links and other output function new_nav_menu_items($items) { $homelink = '<li class="home"><a href="' . home_url( '/' ) . '">' . __('Home') . '</a></...


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