Slow WP-Admin? Boost WP_Admin performance by disabling update checker.

In modern WordPress era things about theme and plugin repositories are far from ideal.

We don’t have centralized “app store” in WordPress world (similar to Apple Store and Google Play Store of mobile platforms) – that’s why we can list at least 3 different branches as defragmented segments:

  1. WordPress.org – where only free plugins are allowed.
  2. ThemeForest+Codecanyon – which doesn’t have own repository, but by using some 3rd party tools it is possible to have repository like channel.
  3. Premium self-hosted plugin/theme markets – Each of them has their own repositories.

Alongside with defragmantation this issue has another negative side – WP-Admin checks updates at background, with some transient-expire logic. When you have just one repository(official one – wordpress.org) – that’s not a problem. But when you are using different 3rd party plugins, it causes nightmare.

Few months ago one of my clients asked me to check why his wp-admin works so slowly.

First as a quick check i made quick monitoring with Query Monitor plugin – and discovered that connecting to external hosts takes 4-10 seconds (!) each time – Some of repositories had a problem with response time – and that was affecting whole wp-admin performance.

So i decided to disable Update Checking in wp-admin, excluding Plugins.php page itself.

I wrote such small snippet and put it to functions.php of the theme:

if(is_admin() and strpos($_SERVER["REQUEST_URI"],'plugins.php')===false){
    remove_all_filters('pre_set_site_transient_update_plugins');
    remove_all_filters('site_transient_update_plugins');
    remove_all_actions('pre_set_site_transient_update_plugins');
    remove_all_actions('site_transient_update_plugins');
}

And that did the JOB. Update checking occurs when the client enters to plugins.php to see of there is an update. And that’s exactly what we needed.

Add custom recipient to WordPress comment notification

WordPress sends email notification to Comment Post Author by default. And if it is a reply, it also send a notification to the comment author.

So, what if we need to send email to a different person, using some different logic?

In that case we can use WP’s corresponding filter, called comment_notification_recipients.

This filter sits in wp-includes/pluggable.php.

So, we just add this small snippet to functions.php file of our active theme:

add_filter( 'comment_notification_recipients',function( $emails, $comment_ID){
    $emails[]='[email protected]';
    return $emails;
},10,2);

What if this email should be fetched by using some logic, f.e. there is special meta field in each post, where we need to fetch it from. Here is how it should look like:

add_filter( 'comment_notification_recipients',function( $emails, $comment_ID){
    $comment_obj=get_comment($comment_ID);
    if(!empty($comment_obj->comment_post_ID)){
        $email_owner=get_post_meta($comment_obj->comment_post_ID,
                      'email_meta_field',true); 
        if(is_email($email_owner))$emails[]=$email_owner;
    }
    return $emails;
},10,2);

That’s all. If any question on this subject, you can leave a reply. Don’t forget to subscribe my newsletter feed club to get more and more useful small snippets for WP websites.

Removing added Class Methods from Action/Filters in WordPress

To remove independent function from WP actions/filters is easy thing, we know. We just set remove_action(‘action_name’, ‘function_name’, PRIORITY); and that’s all.

But this simple way doesn’t work for Class Methods. That’s why there is another approach for classes.

remove_action('action_name', array($class_object_variable,'method_name'), PRIORITY);

Well, in some cases this method doesn’t help us either. f.e. When we shouldn’t re-construct that class. (if we declare some $obj=new CLASSNAME(), its construct method re-triggers, and some cases it may cause some problems)

So, what personally i use is guaranteed way – To list already added actions, detect the one we are looking for, get its temporary name generated by WP, and remove it.

In my case i will remove “woocommerce_proceed_to_checkout” action added by third party plugin’s class method “display_form” (priority=9 in my case). Here is how it looks:

add_action('init',function(){
  global $wp_filter;
  if(!empty($wp_filter["woocommerce_proceed_to_checkout"][9])){
    foreach($wp_filter["woocommerce_proceed_to_checkout"][9] as $key=>$removed){
      if(strpos($key,'display_form')!==false){
        remove_action( 'woocommerce_proceed_to_checkout', $key, 9 );
      }
    }
  }
},100);

Simple way to run WP Scheduled Crons

WordPress and Cron Jobs

As we know, by default WordPress is using its own pseudo-cron logic. It just runs at background, and while visitors don’t notice it, actual cron jobs runs when they are browsing our website.

Due to performance issues some developers decide disabling this auto-run at background and use custom calling instead.

For this purpose they simple add

 define('DISABLE_WP_CRON', 'true');

to wp-config.php file and then they add real cron job to their server’s crontab. Like this

* * * * * php /var/www/html/wp-cron.php

So it solves all problems. But, not all actually. I have faced some plugin’s where scheduled tasks are using some front-end data which doesn’t exist in php-cli mode.

That’s why for those cases i use simple trick.

Hybrid Solution – Keeping WP_Cron disabled at front-end, but with one exception.

Here is my code in crontab:

#you can keep this as well * * * * * php /var/www/html/wp-cron.php
*/5 * * * * wget --delete-after -qO- https://www.SITENAME.com/?custom_cron=1

And here is my code in wp-config.php

if(empty($_GET["custom_cron"])) define('DISABLE_WP_CRON', 'true');

These 2 small codes are doing this:

  • They are keeping wp_cron disabled for all visitors. So, no any according slowing down.
  • They let wp_cron to be enabled when custom_cron GET parameter exists.
  • And each 5 minutes, crontab calls https://www.SITENAME.com/?custom_cron=1 URL and runs all tasks via wp’s own cron.

Quick trick – running wp-cli command via Cron Job

WP-Cli via Cron Job in Crontab

Today i faced strange issue with WP-Cli command.

I have simple php script (let’s call it task.php) which runs through Crontab. All blocks of main procedure were running OK except one. That one with

shell_exec("cd /var/www/appname;wp COMMAND_HERE");

Nothing special, just one line of simple shell command.

I run the script in SSH Console

cd /var/www/appname; php task.php

and everything works OK, included shell_exec line.

But same script behaves differently when it is called from cronjob.

After quick investigation i noticed that it was because of WP command.

In cronjob the system doesn’t recognize this command for some already known reasons for me.

That’s why i had to set full path of WP command. And it started working.

Thus, if you face such problem, just replate this

shell_exec("cd /var/www/appname;wp COMMAND_HERE");

with this

shell_exec("cd /var/www/appname; /usr/local/bin/wp COMMAND_HERE");

And it will start working OK.

Restrict wp-admin access by IP – when you are using Cloudflare

Restricting your wp-admin access by using simple Apache’s .htaccess rules is easy, we know.

How to restrict admin access on wordpress?

Just this rule and that’s all

<Files wp-login.php>
Order Deny,Allow
Deny from all
Allow from IP1
Allow from IP2 
#and so on
</Files>

But this would not work if you are using Cloudflare. Just because Cloudflare is middle layer between your website and your website visitor, and you get request with Cloudflare’s own IP-s, not clients’ IP-s.

In order not to lose this information about visitor IP, Cloudflare sends us real visitor’s IP as $_SERVER[‘CF-Connecting-IP’] variable.

So, we just need to adjust our htaccess rule and pass $_SERVER variable there, instead of using IP addresses.

Here is simple htaccess code which works OK with Cloudflare:

SetEnvIF CF-Connecting-IP "SOMEIPHERE1" MyIP
SetEnvIF CF-Connecting-IP "SOMEIPHERE2" MyIP2
<Files wp-login.php>
Require env MyIP
Require env MyIP2
</Files>

That’s all. After saving this block to htaccess, your wp-admin would open for specified IP addresses only.

Easy way to collect all SQL queries in WordPress – with and without SAVEQUERIES enabled

As we know WordPress has built in DB class called WPDB and all SQL queries should run via that class.

And in WordPress Debugging the only way to collect/debug executed SQL queries is activating debug constant called SAVEQUERIES.

And this constant forces WPDB to collect all SQL queries – but to display or save those queries we need to use some custom function.

Q: Where to run that function?

A: Usually it is recommended to add saving function to wp_footer hook – simply because wp_footer runs after most processes are finished. (and admin_footer for wp_admin)

But this is totally wrong! Why? Just because wp_footer runs in template side and doesn’t include some processes such as AJAX processes.

So we need to use another hook for that.

Here are 2 simple ways to catch all SQL queries of WPDB.

Continue reading “Easy way to collect all SQL queries in WordPress – with and without SAVEQUERIES enabled”