SlideShare une entreprise Scribd logo
1  sur  43
Télécharger pour lire hors ligne
An Introduction to


Advanced Caching
   methods in WordPress
Maor Chasen


WP Developer @ illuminea
Core contributor for 3.5
Have plugins on WordPress.org
Open Source Fanatic
Design Enthusiast
Flying kites
Intro to advanced caching in WordPress
It's not scary.


It's fun.
Why caching is good for you?
A question you shouldn't ask your mom



 1. It's easy
 2. Your site = faster
 3. Can save you $$
 4. It will knock
    your socks off
 5. You'll sleep better
    at night.
What we will talk about
● What is fragment / object caching

● Why caching is important

● How to cache

● What to cache

● When to cache
What we won't talk about
● Server setups

● Caching plugins
Intro to advanced caching in WordPress
first things first

Transients API
Transients are
●   temporary bits of data (usually raw data)
●   like options, but w/ expiration time
●   always persistent out of the box
●   stored in wp_options by default

●   stored in memory if a caching backend (APC,
    Memcache, XCache, etc.) is available
●   available since 2.8
Use Transients when
●   fetching data from a remote source
●   performing an expensive* query or request
    ○   meta_query
    ○   tax_query
●   data persistence is absolutely required**

* operations that require high CPU usage or high latency (Identify slow
queries with Debug Bar)
** ex. - when polling data from external sources
Transients functions
at your disposal




read core?
wp-includes/option.php
Get it.
get_transient( $transient );




     unique string (key) representing a piece of data
Set it.
set_transient(
  $transient,
  $value,         the data you wish to store
  $expiration = 0             for how long?
);
Scrap it.
delete_transient( $transient );




     unique string (key) representing a piece of data
Multisite?
You're in luck! All Transients functions
have their network-wide counterparts.

get_site_transient();
set_site_transient();
delete_site_transient();
Use case:
Using Transients to store
fragmented data
wp_nav_menu( array(
   'theme_location' => 'primary',
) );




<ul id="menu-primary" class="menu">
        <li id="menu-item-10" class="menu-item">
                <a href="...">...</a>
        </li>
        ...
</ul>
Without using
wp_nav_menu()



After using
wp_nav_menu()



     That is ~5 extra queries
                (for each menu)
Instead, we can cache the
menu in a transient
and save on DB queries
// Get an existing copy of our transient data
$menu_html = get_transient( 'wcj_2013_menu' );

if ( false === $menu_html ) {
        // data is not available, let's generate it
        $menu_html = wp_nav_menu( array(
                'theme_location' => 'primary',           returns the
                'echo' => false,                         menu instead
        ) );                                             of printing
        set_transient( 'wcj_2013_menu', $menu_html, DAY_IN_SECONDS );
}

// do something with $menu_html
echo $menu_html;                                  60 * 60 * 24
// Get an existing copy of our transient data
$menu_html = get_transient( 'wcj_2013_menu' );

if ( false === $menu_html ) {
        // data is not available, let's generate it
        $menu_html = wp_nav_menu( array(
                'theme_location' => 'primary',
                'echo' => false,
        ) );
        set_transient( 'wcj_2013_menu', $menu_html );
}

// do something with $menu_html
echo $menu_html;       doesn't    expire, but it might anyway
Now, let's invalidate
function wcj_2013_invldt_menu( $menu_id, $menu_data ) {
        delete_transient( 'wcj_2013_menu' );
}
add_action( 'wp_update_nav_menu', 'wcj_2013_invldt_menu', 10, 2 );




  this action runs whenever a menu is being saved
Use Transients when fetching
data from a remote source

http://...
https://...
Pick your poison

 Twitter API
Facebook API    last.fm API

       Google+ API
Example (Twitter API):
Retrieve follower count
and cache the results
function wcj_2013_get_twitter_followers_for( $handle ) {
        $key = "wcj_2013_followers_$handle";

        if ( false === ( $followers_count = get_transient( $key ) ) ) {
                // transient expired, regenerate!
                $followers_count = wp_remote_retrieve_body(
                        wp_remote_get( "http://api.twitter.com/1/users/show.json?
screen_name=$handle" )
                );

               // request failed?
               if ( empty( $followers_count ) )
                       return false;

               // extract the number of followers
               $json = (object) json_decode( $followers_count );
               $followers_count = absint( $json->followers_count );

               // request was complete, store data in a transient for 6 hours
               set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS );
        }
        return $followers_count;
}
function wcj_2013_get_twitter_followers_for( $handle ) {
        $key = "wcj_2013_followers_$handle";

        if ( false === ( $followers_count = get_transient( $key ) ) ) {
                // transient expired, regenerate!
                $followers_count = wp_remote_retrieve_body(
                        wp_remote_get( "http://api.twitter.com/1/users/show.json?
screen_name=$handle" )
                );

                // request failed?
                if ( empty( $followers_count ) )
                        return false;

               // extract the number of followers
               $json = (object) json_decode( $followers_count );
               $followers_count = absint( $json->followers_count );

               // request was complete, store data in a transient for 6 hours
               set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS );
        }
        return $followers_count;
}
function wcj_2013_get_twitter_followers_for( $handle ) {
        $key = "wcj_2013_followers_$handle";

        if ( false === ( $followers_count = get_transient( $key ) ) ) {
                // transient expired, regenerate!
                $followers_count = wp_remote_retrieve_body(
                        wp_remote_get( "http://api.twitter.com/1/users/show.json?
screen_name=$handle" )
                );

                // request failed?
                if ( empty( $followers_count ) )
                        return false;

                // extract the number of followers
                $json = (object) json_decode( $followers_count );
                $followers_count = absint( $json->followers_count );

               // request was complete, store data in a transient for 6 hours
               set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS );
        }
        return $followers_count;
}
function wcj_2013_get_twitter_followers_for( $handle ) {
        $key = "wcj_2013_followers_$handle";

        if ( false === ( $followers_count = get_transient( $key ) ) ) {
                // transient expired, regenerate!
                $followers_count = wp_remote_retrieve_body(
                        wp_remote_get( "http://api.twitter.com/1/users/show.json?
screen_name=$handle" )
                );

                // request failed?
                if ( empty( $followers_count ) )
                        return false;

                // extract the number of followers
                $json = (object) json_decode( $followers_count );
                $followers_count = absint( $json->followers_count );

               // request was complete, store data in a transient for 6 hours
               set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS );
        }
        return $followers_count;
}

printf( 'I have %d followers!', wcj_2013_get_twitter_followers_for( 'maorh' ) );
Let's spice it up
Got some metrics!
Without Transients
0.36014295 seconds


WITH Transients
0.00010109 seconds
That is


3,562 X FASTER
Intro to advanced caching in WordPress
last but not least

Object Cache API
Object Cache is
●   non-persistent out of the box
●   stored in PHP memory by default
●   ideally* persistent when a caching backend is
    available
●   similar to Transients
●   available since 2.0
* Success depends on server environment
Common use of the Object Cache API

                                          DB
        Is post_id
            = 13            No         SELECT *
          cached?                        FROM
                                       wp_posts
                                      WHERE ID =
                                          13


            Yes




   Do something with that        Store results in Object
           post                          Cache
Object Cache functions
at your disposal




read core?
wp-includes/cache.php
Object Cache functions
at your disposal
●   wp_cache_add( $k, $d, $g, $ex )
●   wp_cache_get( $k )
●   wp_cache_set( $k, $d, $g, $ex )
●   wp_cache_delete( $k, $g )
●   wp_cache_incr( $k, $offset, $g )

$key, $data, $group, $expiration
Example
$song_obj = wp_cache_get( $id, 'songs' );

if ( false === $song_obj ) {
        $song_obj = $wpdb->get_row(
                $wpdb->prepare( "SELECT * FROM
$wpdb->songs WHERE ID = %d", $id )
        );
        wp_cache_set( $id, $song_obj, 'songs' );
}
// do something with $song_obj
Best Practices
for the best of us
● prefer refreshing the cache ONLY when data is
   added/changed
● Avoid, if possible, caching on front end page requests
   (instead, generate the data on an admin event*)
● Design to fail gracefully (never assume that data is in the
   cache)

* useful events: publish_post, transition_post_status, created_
{$taxonomy}, edited_{$taxonomy}
Side-by-side comparison
                                                        Memory Cache
                                   Out of the box
                                                          Backend



    Transients API              persistent - database      Persistent



                                   non-persistent -
   Object Cache API                                     Ideally Persistent
                                      memory



http://wordpress.stackexchange.com/a/45137
Thanks!
Questions?
@maorh
keep in touch

Contenu connexe

Tendances

Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHPGuilherme Blanco
 
When cqrs meets event sourcing
When cqrs meets event sourcingWhen cqrs meets event sourcing
When cqrs meets event sourcingManel Sellés
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDAleix Vergés
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ EtsyNishan Subedi
 
Object Calisthenics Adapted for PHP
Object Calisthenics Adapted for PHPObject Calisthenics Adapted for PHP
Object Calisthenics Adapted for PHPChad Gray
 
Doctrine 2
Doctrine 2Doctrine 2
Doctrine 2zfconfua
 
WooCommerce CRUD and Data Store by Akeda Bagus
WooCommerce CRUD and Data Store by Akeda BagusWooCommerce CRUD and Data Store by Akeda Bagus
WooCommerce CRUD and Data Store by Akeda BagusWordCamp Indonesia
 
Gta v savegame
Gta v savegameGta v savegame
Gta v savegamehozayfa999
 
Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB jhchabran
 
WordPress plugin #3
WordPress plugin #3WordPress plugin #3
WordPress plugin #3giwoolee
 
WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress
WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress
WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress WordCamp Kyiv
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mockingKonstantin Kudryashov
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConRafael Dohms
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介Jace Ju
 
Simple Photo Processing and Web Display with Perl
Simple Photo Processing and Web Display with PerlSimple Photo Processing and Web Display with Perl
Simple Photo Processing and Web Display with PerlKent Cowgill
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...Rafael Dohms
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonfRafael Dohms
 
HirshHorn theme: how I created it
HirshHorn theme: how I created itHirshHorn theme: how I created it
HirshHorn theme: how I created itPaul Bearne
 

Tendances (20)

Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHP
 
When cqrs meets event sourcing
When cqrs meets event sourcingWhen cqrs meets event sourcing
When cqrs meets event sourcing
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
Object Calisthenics Adapted for PHP
Object Calisthenics Adapted for PHPObject Calisthenics Adapted for PHP
Object Calisthenics Adapted for PHP
 
Doctrine 2
Doctrine 2Doctrine 2
Doctrine 2
 
WooCommerce CRUD and Data Store by Akeda Bagus
WooCommerce CRUD and Data Store by Akeda BagusWooCommerce CRUD and Data Store by Akeda Bagus
WooCommerce CRUD and Data Store by Akeda Bagus
 
Gta v savegame
Gta v savegameGta v savegame
Gta v savegame
 
Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB
 
Coding website
Coding websiteCoding website
Coding website
 
WordPress plugin #3
WordPress plugin #3WordPress plugin #3
WordPress plugin #3
 
WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress
WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress
WordPress Kitchen 2014 - Александр Стриха: Кеширование в WordPress
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介
 
Simple Photo Processing and Web Display with Perl
Simple Photo Processing and Web Display with PerlSimple Photo Processing and Web Display with Perl
Simple Photo Processing and Web Display with Perl
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
 
Hacking Movable Type
Hacking Movable TypeHacking Movable Type
Hacking Movable Type
 
HirshHorn theme: how I created it
HirshHorn theme: how I created itHirshHorn theme: how I created it
HirshHorn theme: how I created it
 

Similaire à Intro to advanced caching in WordPress

WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...andrewnacin
 
AngularJS - $http & $resource Services
AngularJS - $http & $resource ServicesAngularJS - $http & $resource Services
AngularJS - $http & $resource ServicesEyal Vardi
 
Caching in WordPress
Caching in WordPressCaching in WordPress
Caching in WordPressTareq Hasan
 
Temporary Cache Assistance (Transients API): WordCamp Phoenix 2014
Temporary Cache Assistance (Transients API): WordCamp Phoenix 2014Temporary Cache Assistance (Transients API): WordCamp Phoenix 2014
Temporary Cache Assistance (Transients API): WordCamp Phoenix 2014Cliff Seal
 
Temporary Cache Assistance (Transients API): WordCamp Birmingham 2014
Temporary Cache Assistance (Transients API): WordCamp Birmingham 2014Temporary Cache Assistance (Transients API): WordCamp Birmingham 2014
Temporary Cache Assistance (Transients API): WordCamp Birmingham 2014Cliff Seal
 
Speed Things Up with Transients
Speed Things Up with TransientsSpeed Things Up with Transients
Speed Things Up with TransientsCliff Seal
 
Options, and Transients, and Theme Mods — Oh my!
Options, and Transients, and Theme Mods — Oh my!Options, and Transients, and Theme Mods — Oh my!
Options, and Transients, and Theme Mods — Oh my!Konstantin Obenland
 
Magento Dependency Injection
Magento Dependency InjectionMagento Dependency Injection
Magento Dependency InjectionAnton Kril
 
MUC - Moodle Universal Cache
MUC - Moodle Universal CacheMUC - Moodle Universal Cache
MUC - Moodle Universal CacheTim Hunt
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web servicesMichelangelo van Dam
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Transients are good for you - WordCamp London 2016
Transients are good for you - WordCamp London 2016Transients are good for you - WordCamp London 2016
Transients are good for you - WordCamp London 2016Boiteaweb
 
Lazy evaluation drupal camp moscow 2014
Lazy evaluation drupal camp moscow 2014Lazy evaluation drupal camp moscow 2014
Lazy evaluation drupal camp moscow 2014Evgeny Nikitin
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous phpWim Godden
 
Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionPhilip Norton
 
Introduction to the WordPress Transients API
Introduction to the WordPress Transients APIIntroduction to the WordPress Transients API
Introduction to the WordPress Transients APItopher1kenobe
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From IusethisMarcus Ramberg
 
Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)andrewnacin
 

Similaire à Intro to advanced caching in WordPress (20)

WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
 
AngularJS - $http & $resource Services
AngularJS - $http & $resource ServicesAngularJS - $http & $resource Services
AngularJS - $http & $resource Services
 
Caching in WordPress
Caching in WordPressCaching in WordPress
Caching in WordPress
 
Temporary Cache Assistance (Transients API): WordCamp Phoenix 2014
Temporary Cache Assistance (Transients API): WordCamp Phoenix 2014Temporary Cache Assistance (Transients API): WordCamp Phoenix 2014
Temporary Cache Assistance (Transients API): WordCamp Phoenix 2014
 
Temporary Cache Assistance (Transients API): WordCamp Birmingham 2014
Temporary Cache Assistance (Transients API): WordCamp Birmingham 2014Temporary Cache Assistance (Transients API): WordCamp Birmingham 2014
Temporary Cache Assistance (Transients API): WordCamp Birmingham 2014
 
Speed Things Up with Transients
Speed Things Up with TransientsSpeed Things Up with Transients
Speed Things Up with Transients
 
Options, and Transients, and Theme Mods — Oh my!
Options, and Transients, and Theme Mods — Oh my!Options, and Transients, and Theme Mods — Oh my!
Options, and Transients, and Theme Mods — Oh my!
 
Magento Dependency Injection
Magento Dependency InjectionMagento Dependency Injection
Magento Dependency Injection
 
MUC - Moodle Universal Cache
MUC - Moodle Universal CacheMUC - Moodle Universal Cache
MUC - Moodle Universal Cache
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
 
Feeds drupal cafe
Feeds drupal cafeFeeds drupal cafe
Feeds drupal cafe
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Transients are good for you - WordCamp London 2016
Transients are good for you - WordCamp London 2016Transients are good for you - WordCamp London 2016
Transients are good for you - WordCamp London 2016
 
Lazy evaluation drupal camp moscow 2014
Lazy evaluation drupal camp moscow 2014Lazy evaluation drupal camp moscow 2014
Lazy evaluation drupal camp moscow 2014
 
The promise of asynchronous php
The promise of asynchronous phpThe promise of asynchronous php
The promise of asynchronous php
 
Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency Injection
 
Introduction to the WordPress Transients API
Introduction to the WordPress Transients APIIntroduction to the WordPress Transients API
Introduction to the WordPress Transients API
 
Separation of concerns - DPC12
Separation of concerns - DPC12Separation of concerns - DPC12
Separation of concerns - DPC12
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)
 

Intro to advanced caching in WordPress

  • 1. An Introduction to Advanced Caching methods in WordPress
  • 2. Maor Chasen WP Developer @ illuminea Core contributor for 3.5 Have plugins on WordPress.org Open Source Fanatic Design Enthusiast Flying kites
  • 5. Why caching is good for you? A question you shouldn't ask your mom 1. It's easy 2. Your site = faster 3. Can save you $$ 4. It will knock your socks off 5. You'll sleep better at night.
  • 6. What we will talk about ● What is fragment / object caching ● Why caching is important ● How to cache ● What to cache ● When to cache
  • 7. What we won't talk about ● Server setups ● Caching plugins
  • 10. Transients are ● temporary bits of data (usually raw data) ● like options, but w/ expiration time ● always persistent out of the box ● stored in wp_options by default ● stored in memory if a caching backend (APC, Memcache, XCache, etc.) is available ● available since 2.8
  • 11. Use Transients when ● fetching data from a remote source ● performing an expensive* query or request ○ meta_query ○ tax_query ● data persistence is absolutely required** * operations that require high CPU usage or high latency (Identify slow queries with Debug Bar) ** ex. - when polling data from external sources
  • 12. Transients functions at your disposal read core? wp-includes/option.php
  • 13. Get it. get_transient( $transient ); unique string (key) representing a piece of data
  • 14. Set it. set_transient( $transient, $value, the data you wish to store $expiration = 0 for how long? );
  • 15. Scrap it. delete_transient( $transient ); unique string (key) representing a piece of data
  • 16. Multisite? You're in luck! All Transients functions have their network-wide counterparts. get_site_transient(); set_site_transient(); delete_site_transient();
  • 17. Use case: Using Transients to store fragmented data
  • 18. wp_nav_menu( array( 'theme_location' => 'primary', ) ); <ul id="menu-primary" class="menu"> <li id="menu-item-10" class="menu-item"> <a href="...">...</a> </li> ... </ul>
  • 19. Without using wp_nav_menu() After using wp_nav_menu() That is ~5 extra queries (for each menu)
  • 20. Instead, we can cache the menu in a transient and save on DB queries
  • 21. // Get an existing copy of our transient data $menu_html = get_transient( 'wcj_2013_menu' ); if ( false === $menu_html ) { // data is not available, let's generate it $menu_html = wp_nav_menu( array( 'theme_location' => 'primary', returns the 'echo' => false, menu instead ) ); of printing set_transient( 'wcj_2013_menu', $menu_html, DAY_IN_SECONDS ); } // do something with $menu_html echo $menu_html; 60 * 60 * 24
  • 22. // Get an existing copy of our transient data $menu_html = get_transient( 'wcj_2013_menu' ); if ( false === $menu_html ) { // data is not available, let's generate it $menu_html = wp_nav_menu( array( 'theme_location' => 'primary', 'echo' => false, ) ); set_transient( 'wcj_2013_menu', $menu_html ); } // do something with $menu_html echo $menu_html; doesn't expire, but it might anyway
  • 23. Now, let's invalidate function wcj_2013_invldt_menu( $menu_id, $menu_data ) { delete_transient( 'wcj_2013_menu' ); } add_action( 'wp_update_nav_menu', 'wcj_2013_invldt_menu', 10, 2 ); this action runs whenever a menu is being saved
  • 24. Use Transients when fetching data from a remote source http://... https://...
  • 25. Pick your poison Twitter API Facebook API last.fm API Google+ API
  • 26. Example (Twitter API): Retrieve follower count and cache the results
  • 27. function wcj_2013_get_twitter_followers_for( $handle ) { $key = "wcj_2013_followers_$handle"; if ( false === ( $followers_count = get_transient( $key ) ) ) { // transient expired, regenerate! $followers_count = wp_remote_retrieve_body( wp_remote_get( "http://api.twitter.com/1/users/show.json? screen_name=$handle" ) ); // request failed? if ( empty( $followers_count ) ) return false; // extract the number of followers $json = (object) json_decode( $followers_count ); $followers_count = absint( $json->followers_count ); // request was complete, store data in a transient for 6 hours set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS ); } return $followers_count; }
  • 28. function wcj_2013_get_twitter_followers_for( $handle ) { $key = "wcj_2013_followers_$handle"; if ( false === ( $followers_count = get_transient( $key ) ) ) { // transient expired, regenerate! $followers_count = wp_remote_retrieve_body( wp_remote_get( "http://api.twitter.com/1/users/show.json? screen_name=$handle" ) ); // request failed? if ( empty( $followers_count ) ) return false; // extract the number of followers $json = (object) json_decode( $followers_count ); $followers_count = absint( $json->followers_count ); // request was complete, store data in a transient for 6 hours set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS ); } return $followers_count; }
  • 29. function wcj_2013_get_twitter_followers_for( $handle ) { $key = "wcj_2013_followers_$handle"; if ( false === ( $followers_count = get_transient( $key ) ) ) { // transient expired, regenerate! $followers_count = wp_remote_retrieve_body( wp_remote_get( "http://api.twitter.com/1/users/show.json? screen_name=$handle" ) ); // request failed? if ( empty( $followers_count ) ) return false; // extract the number of followers $json = (object) json_decode( $followers_count ); $followers_count = absint( $json->followers_count ); // request was complete, store data in a transient for 6 hours set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS ); } return $followers_count; }
  • 30. function wcj_2013_get_twitter_followers_for( $handle ) { $key = "wcj_2013_followers_$handle"; if ( false === ( $followers_count = get_transient( $key ) ) ) { // transient expired, regenerate! $followers_count = wp_remote_retrieve_body( wp_remote_get( "http://api.twitter.com/1/users/show.json? screen_name=$handle" ) ); // request failed? if ( empty( $followers_count ) ) return false; // extract the number of followers $json = (object) json_decode( $followers_count ); $followers_count = absint( $json->followers_count ); // request was complete, store data in a transient for 6 hours set_transient( $key, $followers_count, 6 * HOUR_IN_SECONDS ); } return $followers_count; } printf( 'I have %d followers!', wcj_2013_get_twitter_followers_for( 'maorh' ) );
  • 31. Let's spice it up Got some metrics!
  • 32. Without Transients 0.36014295 seconds WITH Transients 0.00010109 seconds
  • 33. That is 3,562 X FASTER
  • 35. last but not least Object Cache API
  • 36. Object Cache is ● non-persistent out of the box ● stored in PHP memory by default ● ideally* persistent when a caching backend is available ● similar to Transients ● available since 2.0 * Success depends on server environment
  • 37. Common use of the Object Cache API DB Is post_id = 13 No SELECT * cached? FROM wp_posts WHERE ID = 13 Yes Do something with that Store results in Object post Cache
  • 38. Object Cache functions at your disposal read core? wp-includes/cache.php
  • 39. Object Cache functions at your disposal ● wp_cache_add( $k, $d, $g, $ex ) ● wp_cache_get( $k ) ● wp_cache_set( $k, $d, $g, $ex ) ● wp_cache_delete( $k, $g ) ● wp_cache_incr( $k, $offset, $g ) $key, $data, $group, $expiration
  • 40. Example $song_obj = wp_cache_get( $id, 'songs' ); if ( false === $song_obj ) { $song_obj = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->songs WHERE ID = %d", $id ) ); wp_cache_set( $id, $song_obj, 'songs' ); } // do something with $song_obj
  • 41. Best Practices for the best of us ● prefer refreshing the cache ONLY when data is added/changed ● Avoid, if possible, caching on front end page requests (instead, generate the data on an admin event*) ● Design to fail gracefully (never assume that data is in the cache) * useful events: publish_post, transition_post_status, created_ {$taxonomy}, edited_{$taxonomy}
  • 42. Side-by-side comparison Memory Cache Out of the box Backend Transients API persistent - database Persistent non-persistent - Object Cache API Ideally Persistent memory http://wordpress.stackexchange.com/a/45137