Clear PHP opcode caches before WordPress Updates: ease the updating process

Reading Time: 11 Minutes
It's only fair to share...
Share on Facebook3Tweet about this on TwitterShare on LinkedIn1Share on Google+1

In various hosting environments, WordPress core-, plugin- and theme updates sometimes fail because of enabled opcode caches. Popular PHP opcode caches are OPcache, WinCache and APC. This little WordPress Must Use Plugin tries to flush opcode caches. Making your live a bit easier when updating WordPress Core, Plugins and Themes.

Advertisement:

For this mu-plugin to function only on WordPress Core-, Plugin- and Theme-updates, it hooks into WordPress’ upgrader_pre_install filter hook:

Filters the install response before the installation has started.

You can use the upgrader_pre_install hook to execute a function before an update is installed. For example a function to flush OPcache cache, easing the update process and hopefully preventing update failures due to this opcode cache. Furthermore, it also prevents a stale (cached) “Please update!” notices.

Flush OPcache MU-Plugin #

This WordPress mu-plugin is meant as an example, to show you how easy it can be to flush PHP caches. It’s provided “AS-IS”. You are free to use and extend it, but please do credit me though ;-) . It currently supports PHP OPcache and WinCache, but you can easily extend it for APC (for example).

Before trying to flush the cache, the plugin tries to determine whether or not the PHP extensions are loaded and active on your web server. The plugin logs success and failure through PHP’s error_log() function, meaning: check your WordPress Debug log for results.

Save the following PHP code in a new file called clear-php-opcode-caches.php, and upload it to your wp-content/mu-plugins folder. It’ll be activated automatically.

<?php
/**
 * Plugin Name: Clear PHP opcode caches
 * Plugin URI: https://www.saotn.org/wordpress-plugin-flush-php-opcache/
 * Donate Link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=J24FGGU96YSUY
 * Description: Clears out various PHP opcode and user caches. Currently it tries to clear-out, or flush, PHP OPcache and WinCache caches from memory. This should ease WordPress updates and plugin activation / deactivation.
 * Network: True
 * Version: 1.0
 * Author: Jan Reilink
 * Author URI: https://www.saotn.org
 * License: GPLv2
 */

function clear_iis_wincache() {
    if( ! function_exists( 'wincache_ucache_get' ) ) {
        return;
    }
    if( ! wincache_ucache_clear() ) {
        return false;
    }
    else {
        return true;
    }
}

function clear_php_opcache() {
    if( ! extension_loaded( 'Zend OPcache' ) ) {
        return;
    }
    $opcache_status = opcache_get_status();
    if( false === $opcache_status["opcache_enabled"] ) {
        // extension loaded but OPcache not enabled
        return;
    }
    if( ! opcache_reset() ) { 
        return false;
    }
    else {
        /**
         * opcache_reset() is performed, now try to clear the 
         * file cache.
         * Please note: http://stackoverflow.com/a/23587079/1297898
         *  "Opcache does not evict invalid items from memory - they 
         *   stay there until the pool is full at which point the 
         *   memory is completely cleared"
         */
        foreach( $opcache_status['scripts'] as $key => $data ) {
            $dirs[dirname( $key )][basename( $key )] = $data;
            opcache_invalidate( $data['full_path'] , $force = true );
        }
        return true;
    }
}

function is_iis() {
    $software = strtolower( $_SERVER["SERVER_SOFTWARE"] );
    if( false !== strpos( $software, "microsoft-iis" ) )
        return true;
    else
        return false;
}

function clear_caches() {
    if( is_iis() ) {
        if ( clear_iis_wincache() ) {
            error_log( 'WinCache user cache cleared.' );
        }
        else {
            error_log( 'Clearing WinCache user cache opcode cache failed.' );
        }
    }
    if( clear_php_opcache() ) {
        error_log( 'PHP OPcache opcode cache cleared.' );
    }
    else {
        error_log( 'Clearing PHP OPcache opcode cache failed.' );
    }
}
add_filter('plugin_row_meta', 'saotn1_plugin_row_meta', 10, 2);
function saotn1_plugin_row_meta($links, $file) {
    if ( !preg_match('/clear-opcode-caches.php$/', $file ) ) {
      return $links;
    }
        
    $links[] = sprintf(
      '%s',
      __( 'Donate' )
    );
    return $links;
}
add_filter('upgrader_pre_install', 'clear_caches', 10, 2);
?>

That’s all! Now this mu-plugin’s clear_caches() function is ran before every WordPress update, whether it is a Core-, Plugin- or Theme update.

Related:   Custom PHP version on IIS Express and WebMatrix 3

Why is this plugin important? #

Now the OPcache module is in the PHP core, you might run into cache misses and errors when upgrading WordPress. For example, in WordPress 4.7, get_paged_template() was moved to wp-includes/deprecated.php. A fatal fatal error might be thrown when PHP’s internal OPcache still points to wp-includes/template.php (source by @swissspidy).

A second problem is that WordPress sometimes is not able to install and apply updates. An error message “Could not copy file. index.php” followed up with “Installation failed” is displayed in the Dashboard. Stale opcode cache might be the cause of this, and currently there is a running Trac ticket on the subject: Call opcache_reset() after plug-in, theme or core update.

Extend the plugin and clear APC cache #

As said, you can easily extend the functionality of this mu-plugin. For example to clear APC / APCu cache.

To flush APC caches, you can use the PHP function apc_clear_cache(). See the following example:


/**
 * Follow me on Twitter: @HertogJanR
 */
function clear_apc_cache() {
    if( ! extension_loaded( 'apc' ) ) {
        // APC extension not loaded
        return;
    }
    else {
        if( apc_clear_cache( 'opcode' ) ) {
            error_log( 'APC opcode cache flushed' );
        }
        else {
            error_log(' Flushing APC opcode cache failed' );
        }
        if( apc_clear_cache( 'user' ) ) {
            error_log( 'APC user cache flushed' );
        }
        else {
            error_log( 'Flushing APC user cache failed' );
        }
    }

    /**
     * APCu is the user cache part of the old APC, without 
     * bytecode caching. OPcache provides opcode caching 
     * for PHP, but no user caching.
     */
    if( ! extension_loaded( 'apcu' ) ) {
        // APCu extension not loaded
        return;
    }
    else {
        if ( apc_clear_cache( 'user' ) ) {
            error_log( 'APC user cache flushed' );
        }
        else {
            error_log( 'Flushing APC user cache failed' );
        }
    }
}

Yes, this code is very verbose for example purposes.

Related:   WordPress and PHP7

Clear PHP opcode caches Readme.txt #

Note: Hooking into upgrader_pre_install() can only be done from a Must Use Plugin, not from a normal plugin.

Loaded by PHP, in alphabetical order, before normal plugins, meaning API hooks added in an mu-plugin apply to all other plugins even if they run hooked-functions in the global namespace.

Here is its current readme.txt.

=== Clear PHP opcode caches ===
Contributors: janr
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=J24FGGU96YSUY
Author: Jan Reilink
Author URI: https://www.saotn.org
Tags: php, opcache cache, purge, apc, wincache, opcache, flush
Requires at least: 4.6
Tested up to: 4.6.1
Stable tag: 1.0
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html

Easily purge various PHP opcode caches like OPcache, WinCache and APC/
APCu. Ease the WordPress updating process.

== License ==
Released under the terms of the GNU General Public License.

== Description ==
In various hosting environments, WordPress core-, plugin- and theme 
updates sometimes fail because of enabled opcode caches. Popular PHP 
opcode caches are OPcache, WinCache and APC/APCu. This mu-plugin tries to 
purge, or clear/flush/invalidate, some of those opcode caches.

This'll make your live a bit easier when updating WordPress Core, 
Plugins and Themes.

The "Clear PHP opcode caches" mu-plugin hooks into `upgrader_pre_install()` 
to execute a function prior to an update, flushing the available 
opcode caches. Furthermore, it also prevents a stale (cached) 
"Please update!" notice. This opcode cache purge mu-plugin is 
particularly handy if used in combination with the Vevida Optimizer 
(https://wordpress.org/plugins/vevida-optimizer/) plugin.

Use Vevida Optimizer to configure WordPress automatic updates.

Before trying to flush the cache, it tries to determine whether 
or not the PHP extensions are loaded and active on your web server. 
It logs success and failure through PHP's error_log() function, 
meaning: check your WordPress Debug log for results, when enabled.

== Installation ==

1. Download the .zip package and unzip
1. Upload the file `clear-opcode-caches.php` to the `wp-content/mu-plugins/` directory

That's it, the Must Use Plugin to flush opcode caches is automatically activated. There is no configuration.

== Frequently Asked Questions ==

None so far.

== Changelog ==
= 1.0 =
* Initial tested version and release.

Download Clear opcode caches (clear-opcode-caches.zip).

Related:   Clean-up WordPress spam comments and meta data

If you have a valuable tip, please let met know and drop me a comment.

It's only fair to share...
Share on Facebook3Tweet about this on TwitterShare on LinkedIn1Share on Google+1

Advertisement:

One Reply to “Clear PHP opcode caches before WordPress Updates: ease the updating process”

Hi! Join the discussion, leave a reply!