SlideShare a Scribd company logo
speed things up with
 transients
@cliffseal
#wptrans
logos-creative.com/
     wcatl
LOL WUTAPI?
is the Transients
The Transients API
“offers a simple and standardized
way of storing cached data in the
database temporarily by giving it a
custom name and a timeframe after
which it will expire and be deleted.”
The Transients API

✓ like Options API, but with expiration
✓ uses fast memory (if configured)
✓ uses database otherwise
Native        Object Cache Plugin

               Persistent
 Option                              N/A
              (database)

               Persistent
Transient                     Persistent (varies)
              (database)

            Non-persistent
 Cache                        Persistent (varies)
              (memory)
                                              Thanks to Rarst.
thetransientsAPI




         Tweets             Friends                Scrobbles

                  Options API: Username, URL, ID



          externalAPIs
thetransientsAPI




         Tag Cloud   Ratings   Custom Queries




      expensivequeries
3
mainfunctions
mainfunctions

        set_transient(
           $transient,
           $value,
           $expiration
        );
         set_transient
mainfunctions


$transient
✓   (string) a unique identifier for your cached data

✓   45 characters or less in length

✓   For site transients, 40 characters or less in length



        set_transientargs
mainfunctions


$value
✓   (array|object) Data to save, either a regular variable or an
    array/object

✓   Handles serialization of complex data for you



        set_transientargs
mainfunctions


$expiration
✓   (integer) number of seconds to keep the data before
    refreshing

✓   Example: 60*60*24 or 86400 (24 hours)



       set_transientargs
mainfunctions



MINUTE_IN_SECONDS   =   60 (seconds)
HOUR_IN_SECONDS     =   60 * MINUTE_IN_SECONDS
DAY_IN_SECONDS      =   24 * HOUR_IN_SECONDS
WEEK_IN_SECONDS     =   7 * DAY_IN_SECONDS
YEAR_IN_SECONDS     =   365 * DAY_IN_SECONDS



        timeconstants
mainfunctions


get_transient($transient);
✓   If the transient does not exist, or has expired, returns false

✓   An integer value of zero/empty could be the stored data

✓   Should not be used to hold plain boolean values; array or
    integers instead


              get_transient
mainfunctions




delete_transient($transient);



      delete_transient
mainfunctions


 set_site_transient();
 get_site_transient();
delete_site_transient();
                These work ‘network wide’.


          wpmultisite
3
exampleusecases
cachetagcloud
cachetagcloud

function get_tag_cloud() {

    if ( false === ( $tag_cloud = get_transient( 'my_tag_cloud' ) ) ) {

        $tag_cloud = wp_tag_cloud( 'echo=0' );
        set_transient( 'my_tag_cloud', $tag_cloud, 60*60*24 );

    } else {

        $tag_cloud = get_transient( 'my_tag_cloud' );

    }

    return $tag_cloud;

}
EXPERT

MODE
cachetagcloud

function edit_term_delete_tag_cloud() {

    delete_transient( 'my_tag_cloud' );

}

add_action( 'edit_post', 'edit_term_delete_tag_cloud' );
cachemyissues
cachemyissues
function we_have_issues() {
    if ( false === ( $issues = get_transient( 'we_have_issues' ) ) ) {
        $response = wp_remote_get('https://api.github.com/repos/twitter/bootstrap/
issues?assignee');
        if ( is_wp_error( $response ) ) {
             $error_message = $response->get_error_message();
            echo "This borked: " . $error_message;
        } else {
             $issues = wp_remote_retrieve_body($response);
             set_transient( 'we_have_issues', $issues, 60*60*24 );
        }
    } else {
        $issues = get_transient( 'we_have_issues' );
    }
    $issues = json_decode($issues, true);
    $issuereturn = '';
    for ( $i = 0; $i < 5; $i++ ) {
        $issuereturn .= "<h3><a href='" . $issues[$i]["html_url"] . "'>".
$issues[$i]["title"] . "</a></h3>";
    }
    return $issuereturn;
}
EXPERT

MODE
cachemyissues
function refresh_my_issues() {
    delete_transient( 'we_have_issues' );
}

if ( is_admin() && isset($_GET['forcedel']) && $_GET['forcedel'] === 'yes' ) {
    refresh_my_issues();
}

function refresh_via_admin_bar() {
    global $wp_admin_bar;
    $wp_admin_bar->add_menu( array(
        'title' => __('Refresh'),
        'href' => admin_url('?forcedel=yes'),
        'id' => 'refresh-issues',
        'parent' => false
    ) );

}

add_action( 'wp_before_admin_bar_render', 'refresh_via_admin_bar' );
cachebigquery
cachebigquery
function query_for_commenters() {
    if ( false === ( $commenters = get_transient( 'top_commenters_cached' ) ) ) {
        global $wpdb;
        $commenters = $wpdb->get_results("
           select count(comment_author) as comments_count, comment_author, comment_type
    ! ! ! from $wpdb->comments
    ! ! ! where comment_type != 'pingback'
    ! ! ! and comment_author != ''
    ! ! ! and comment_approved = '1'
    ! ! ! group by comment_author
    ! ! ! order by comment_author desc
    ! ! ! LIMIT 10
         ");
        set_transient( 'top_commenters_cached', $commenters, 60*60*24 );
    } else {
        $commenters = get_transient( 'top_commenters_cached' );
    }
    $comment_list = '<ol>';
    foreach($commenters as $commenter) {
        $comment_list .= '<li>';
        $comment_list .= $commenter->comment_author;
        $comment_list .= ' (' . $commenter->comments_count . ')';
        $comment_list .= '</li>';
    }
    $comment_list .= '</ol>';
    return $comment_list;
}
cachebigquery

function delete_query_for_commenters() {

    delete_transient( 'top_commenters_cached' );

}

add_action( 'comment_post', 'delete_query_for_commenters' );
cachebigquery
function popular_posts( $num=10 ) {
    if ( false === ( $popular = get_transient( 'popular_posts' . $num ) ) )
{
        $query = new WP_Query( array(
             'orderby' => 'comment_count',
             'posts_per_page' => $num
        ) );
        set_transient( 'popular_posts' . $num, $query, 60*60*24 );
    } else {
        $query = get_transient( 'popular_posts' . $num );
    }

    return $query;
}
cachebigquery

$newquery = popular_posts(3);
if ( $newquery->have_posts() ) {
    while ( $newquery->have_posts() ) {
        $newquery->the_post(); ?>
    <h4><?php the_title(); ?></h4>
        <?php the_excerpt(); ?>
    <?php
    }
    wp_reset_postdata();
}
cachebigquery

function clear_popular_posts() {

    for ( $i = 0; $i < 50; $i++ ) {

        delete_transient( 'popular_posts' . $i );

    }

}

add_action( 'edit_post', 'clear_popular_posts' );
EXPERT

MODE
cachebigquery

    Once a transient expires, it remains so until the new result is saved.
    Heavy traffic can mean too many concurrent MySQL connections.

function popular_posts_panic( $num=10 ) {
    if ( false === ( $popular =
get_transient( 'popular_posts' . $num ) ) ) {
        return '';
    } else {
        $query = get_transient( 'popular_posts' . $num );
    }

     return $query;
}
                                                           Thanks to Andrew Gray for the idea.
cachebigquery

$newquery = popular_posts_panic(3);
if ( $newquery !== '' ) {
    if ( $newquery->have_posts() ) {
        while ( $newquery->have_posts() ) {
            $newquery->the_post(); ?>
        <h4><?php the_title(); ?></h4>
            <?php the_excerpt(); ?>
        <?php
        }
        wp_reset_postdata();
    }
}
cachebigquery
function renew_popular_posts() {
    for ( $i = 0; $i < 50; $i++ ) {
        if ( false === ( $popular = get_transient( 'popular_posts' .
$i ) ) ) {
            delete_transient( 'popular_posts' . $i );
            $query = new WP_Query( array(
                'orderby' => 'comment_count',
                'posts_per_page' => $i
            ) );
            set_transient( 'popular_posts' . $i, $query, 60*60*24*365 );
        }
    }
}

if ( !wp_next_scheduled( 'renew_popular_posts' ) ) {
    wp_schedule_event( time(), 'hourly', 'renew_popular_posts' );
}
TOP OF HACKER NEWS


  CONQUERED
4
warnings
Speed Things Up with Transients
expiry&garbagecollection


✓ everything works on request
✓ expired != deleted, unless requested
✓ unrequested, undeleted transients stay
  until you remove them explicitly
scalarvalues

✓ accepts scalar values (integer, float,
  string or boolean) & non-scalar
  serializable values (arrays, some
  objects)
✓ SimpleXMLElement will FREAK.
  OUT., so convert it to a string or array
  of objects (i.e. simplexml_load_string)
infinitetransients

✓ transients set without an expiration
  time are autoloaded

✓ if you don’t need it on every page, set
  an expiration (even if it’s a year)

✓ consider the Options API for non-
  transient data
cachinggotchas

✓ in some shared hosting environments,
  object caching can be slower than
  using the database; check your host’s
  recommended settings
✓ always use the Transients API to access
  transients; don’t assume they’re in
  the database (or vice versa)
3
usefultools
usefultools




    TLC Transients                               Artiss Transient Cleaner
                       Debug Bar Transients
    Supports soft-                                    Deletes expired
                       Adds panel to Debug
      expiration,                                transients and optimizes
                       Bar with transient info
 background updating                                       table
?
questions
logos-creative.com/
     wcatl

More Related Content

PDF
Temporary Cache Assistance (Transients API): WordCamp Birmingham 2014
PDF
Temporary Cache Assistance (Transients API): WordCamp Phoenix 2014
PDF
Command Bus To Awesome Town
PDF
Things I Believe Now That I'm Old
PDF
Caching and Scaling WordPress using Fragment Caching
PDF
Models and Service Layers, Hemoglobin and Hobgoblins
PDF
ATK 'Beyond The Pizza Guides'
PDF
Perl object ?
Temporary Cache Assistance (Transients API): WordCamp Birmingham 2014
Temporary Cache Assistance (Transients API): WordCamp Phoenix 2014
Command Bus To Awesome Town
Things I Believe Now That I'm Old
Caching and Scaling WordPress using Fragment Caching
Models and Service Layers, Hemoglobin and Hobgoblins
ATK 'Beyond The Pizza Guides'
Perl object ?

What's hot (20)

KEY
MTDDC 2010.2.5 Tokyo - Brand new API
PDF
Database Design Patterns
PDF
PHP tips and tricks
PDF
The History of PHPersistence
TXT
Gta v savegame
KEY
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
PPTX
Drupal7 dbtng
PDF
Doctrine 2
PDF
PHP 5.3 and Lithium: the most rad php framework
PDF
Intro to advanced caching in WordPress
PDF
Drupal - dbtng 25th Anniversary Edition
PDF
From mysql to MongoDB(MongoDB2011北京交流会)
PDF
WordPress as an application framework
PDF
A Tour to MySQL Commands
PDF
Spock and Geb
PDF
The Zen of Lithium
PDF
Everything About PowerShell
KEY
The Query the Whole Query and Nothing but the Query
PDF
What's new in Doctrine
KEY
究極のコントローラを目指す
MTDDC 2010.2.5 Tokyo - Brand new API
Database Design Patterns
PHP tips and tricks
The History of PHPersistence
Gta v savegame
Designing Opeation Oriented Web Applications / YAPC::Asia Tokyo 2011
Drupal7 dbtng
Doctrine 2
PHP 5.3 and Lithium: the most rad php framework
Intro to advanced caching in WordPress
Drupal - dbtng 25th Anniversary Edition
From mysql to MongoDB(MongoDB2011北京交流会)
WordPress as an application framework
A Tour to MySQL Commands
Spock and Geb
The Zen of Lithium
Everything About PowerShell
The Query the Whole Query and Nothing but the Query
What's new in Doctrine
究極のコントローラを目指す
Ad

Similar to Speed Things Up with Transients (20)

PPTX
Transients are good for you - WordCamp London 2016
PDF
Introduction to the WordPress Transients API
PDF
Caching in WordPress
PPTX
Caching, Scaling, and What I've Learned from WordPress.com VIP
PPTX
Lightweight use of transients
PDF
WordPress Transients
PDF
Clug 2012 March web server optimisation
PDF
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
PDF
Options, and Transients, and Theme Mods — Oh my!
PDF
Balancing Act of Caching LoopConf 2018
KEY
Introduction to memcached
PPTX
Consuming & embedding external content in WordPress
ODP
Caching and tuning fun for high scalability
KEY
Caching: A Guided Tour - 10/12/2010
PDF
Cache Rules Everything Around Me
PDF
Your backend architecture is what matters slideshare
PDF
Balancing Act of Caching, WordCamp Europe 2018
PDF
The Need For Speed: Caching Fundamentals
PDF
WordPress Speed & Performance from Pagely's CTO
KEY
DjangoCon 2010 Scaling Disqus
Transients are good for you - WordCamp London 2016
Introduction to the WordPress Transients API
Caching in WordPress
Caching, Scaling, and What I've Learned from WordPress.com VIP
Lightweight use of transients
WordPress Transients
Clug 2012 March web server optimisation
WordCamp San Francisco 2011: Transients, Caching, and the Complexities of Mul...
Options, and Transients, and Theme Mods — Oh my!
Balancing Act of Caching LoopConf 2018
Introduction to memcached
Consuming & embedding external content in WordPress
Caching and tuning fun for high scalability
Caching: A Guided Tour - 10/12/2010
Cache Rules Everything Around Me
Your backend architecture is what matters slideshare
Balancing Act of Caching, WordCamp Europe 2018
The Need For Speed: Caching Fundamentals
WordPress Speed & Performance from Pagely's CTO
DjangoCon 2010 Scaling Disqus
Ad

More from Cliff Seal (20)

PDF
Trust in the Future
PDF
Building Advocates with World-Class Customer Experiences
PDF
Mastering B2B Email
PDF
Death to Boring B2B Marketing, Part 2: Jobs-to-Be-Done
PDF
DIY WordPress Site Management: Configure, Launch, and Maintain
PDF
Inviting Experimentation by Design
PDF
Death to Boring B2B Marketing: How Applying Design Thinking Drives Success
PDF
Introducing WordPress Multitenancy (Wordcamp Vegas/Orlando 2015/WPCampus)
PDF
People Over Pixels: Meaningful UX That Scales
PDF
Friendlier, Safer WordPress Admin Areas
PDF
Meaningful UX At Any Scale
PDF
No one cares about your content (yet): WordCamp Charleston 2014
PDF
Usability, Groupthink, and Authority
PDF
Get Started in Professional WordPress Design & Development
PDF
No One Cares About Your Content (Yet): WordCamp Chicago 2013
PDF
No One Cares About Your Content (Yet): WordCamp Miami 2013
PDF
A Brief History of Metal
PDF
No One Cares About Your Content (Yet): WordCamp Phoenix 2013
PDF
WordPress and Pardot: The World’s Newest Power Couple
PDF
No One Cares About Your Content (Yet): Digital Atlanta 2012
Trust in the Future
Building Advocates with World-Class Customer Experiences
Mastering B2B Email
Death to Boring B2B Marketing, Part 2: Jobs-to-Be-Done
DIY WordPress Site Management: Configure, Launch, and Maintain
Inviting Experimentation by Design
Death to Boring B2B Marketing: How Applying Design Thinking Drives Success
Introducing WordPress Multitenancy (Wordcamp Vegas/Orlando 2015/WPCampus)
People Over Pixels: Meaningful UX That Scales
Friendlier, Safer WordPress Admin Areas
Meaningful UX At Any Scale
No one cares about your content (yet): WordCamp Charleston 2014
Usability, Groupthink, and Authority
Get Started in Professional WordPress Design & Development
No One Cares About Your Content (Yet): WordCamp Chicago 2013
No One Cares About Your Content (Yet): WordCamp Miami 2013
A Brief History of Metal
No One Cares About Your Content (Yet): WordCamp Phoenix 2013
WordPress and Pardot: The World’s Newest Power Couple
No One Cares About Your Content (Yet): Digital Atlanta 2012

Speed Things Up with Transients

  • 1. speed things up with transients
  • 4. LOL WUTAPI? is the Transients
  • 5. The Transients API “offers a simple and standardized way of storing cached data in the database temporarily by giving it a custom name and a timeframe after which it will expire and be deleted.”
  • 6. The Transients API ✓ like Options API, but with expiration ✓ uses fast memory (if configured) ✓ uses database otherwise
  • 7. Native Object Cache Plugin Persistent Option N/A (database) Persistent Transient Persistent (varies) (database) Non-persistent Cache Persistent (varies) (memory) Thanks to Rarst.
  • 8. thetransientsAPI Tweets Friends Scrobbles Options API: Username, URL, ID externalAPIs
  • 9. thetransientsAPI Tag Cloud Ratings Custom Queries expensivequeries
  • 11. mainfunctions set_transient( $transient, $value, $expiration ); set_transient
  • 12. mainfunctions $transient ✓ (string) a unique identifier for your cached data ✓ 45 characters or less in length ✓ For site transients, 40 characters or less in length set_transientargs
  • 13. mainfunctions $value ✓ (array|object) Data to save, either a regular variable or an array/object ✓ Handles serialization of complex data for you set_transientargs
  • 14. mainfunctions $expiration ✓ (integer) number of seconds to keep the data before refreshing ✓ Example: 60*60*24 or 86400 (24 hours) set_transientargs
  • 15. mainfunctions MINUTE_IN_SECONDS = 60 (seconds) HOUR_IN_SECONDS = 60 * MINUTE_IN_SECONDS DAY_IN_SECONDS = 24 * HOUR_IN_SECONDS WEEK_IN_SECONDS = 7 * DAY_IN_SECONDS YEAR_IN_SECONDS = 365 * DAY_IN_SECONDS timeconstants
  • 16. mainfunctions get_transient($transient); ✓ If the transient does not exist, or has expired, returns false ✓ An integer value of zero/empty could be the stored data ✓ Should not be used to hold plain boolean values; array or integers instead get_transient
  • 21. cachetagcloud function get_tag_cloud() { if ( false === ( $tag_cloud = get_transient( 'my_tag_cloud' ) ) ) { $tag_cloud = wp_tag_cloud( 'echo=0' ); set_transient( 'my_tag_cloud', $tag_cloud, 60*60*24 ); } else { $tag_cloud = get_transient( 'my_tag_cloud' ); } return $tag_cloud; }
  • 23. cachetagcloud function edit_term_delete_tag_cloud() { delete_transient( 'my_tag_cloud' ); } add_action( 'edit_post', 'edit_term_delete_tag_cloud' );
  • 25. cachemyissues function we_have_issues() { if ( false === ( $issues = get_transient( 'we_have_issues' ) ) ) { $response = wp_remote_get('https://api.github.com/repos/twitter/bootstrap/ issues?assignee'); if ( is_wp_error( $response ) ) { $error_message = $response->get_error_message(); echo "This borked: " . $error_message; } else { $issues = wp_remote_retrieve_body($response); set_transient( 'we_have_issues', $issues, 60*60*24 ); } } else { $issues = get_transient( 'we_have_issues' ); } $issues = json_decode($issues, true); $issuereturn = ''; for ( $i = 0; $i < 5; $i++ ) { $issuereturn .= "<h3><a href='" . $issues[$i]["html_url"] . "'>". $issues[$i]["title"] . "</a></h3>"; } return $issuereturn; }
  • 27. cachemyissues function refresh_my_issues() { delete_transient( 'we_have_issues' ); } if ( is_admin() && isset($_GET['forcedel']) && $_GET['forcedel'] === 'yes' ) { refresh_my_issues(); } function refresh_via_admin_bar() { global $wp_admin_bar; $wp_admin_bar->add_menu( array( 'title' => __('Refresh'), 'href' => admin_url('?forcedel=yes'), 'id' => 'refresh-issues', 'parent' => false ) ); } add_action( 'wp_before_admin_bar_render', 'refresh_via_admin_bar' );
  • 29. cachebigquery function query_for_commenters() { if ( false === ( $commenters = get_transient( 'top_commenters_cached' ) ) ) { global $wpdb; $commenters = $wpdb->get_results(" select count(comment_author) as comments_count, comment_author, comment_type ! ! ! from $wpdb->comments ! ! ! where comment_type != 'pingback' ! ! ! and comment_author != '' ! ! ! and comment_approved = '1' ! ! ! group by comment_author ! ! ! order by comment_author desc ! ! ! LIMIT 10 "); set_transient( 'top_commenters_cached', $commenters, 60*60*24 ); } else { $commenters = get_transient( 'top_commenters_cached' ); } $comment_list = '<ol>'; foreach($commenters as $commenter) { $comment_list .= '<li>'; $comment_list .= $commenter->comment_author; $comment_list .= ' (' . $commenter->comments_count . ')'; $comment_list .= '</li>'; } $comment_list .= '</ol>'; return $comment_list; }
  • 30. cachebigquery function delete_query_for_commenters() { delete_transient( 'top_commenters_cached' ); } add_action( 'comment_post', 'delete_query_for_commenters' );
  • 31. cachebigquery function popular_posts( $num=10 ) { if ( false === ( $popular = get_transient( 'popular_posts' . $num ) ) ) { $query = new WP_Query( array( 'orderby' => 'comment_count', 'posts_per_page' => $num ) ); set_transient( 'popular_posts' . $num, $query, 60*60*24 ); } else { $query = get_transient( 'popular_posts' . $num ); } return $query; }
  • 32. cachebigquery $newquery = popular_posts(3); if ( $newquery->have_posts() ) { while ( $newquery->have_posts() ) { $newquery->the_post(); ?> <h4><?php the_title(); ?></h4> <?php the_excerpt(); ?> <?php } wp_reset_postdata(); }
  • 33. cachebigquery function clear_popular_posts() { for ( $i = 0; $i < 50; $i++ ) { delete_transient( 'popular_posts' . $i ); } } add_action( 'edit_post', 'clear_popular_posts' );
  • 35. cachebigquery Once a transient expires, it remains so until the new result is saved. Heavy traffic can mean too many concurrent MySQL connections. function popular_posts_panic( $num=10 ) { if ( false === ( $popular = get_transient( 'popular_posts' . $num ) ) ) { return ''; } else { $query = get_transient( 'popular_posts' . $num ); } return $query; } Thanks to Andrew Gray for the idea.
  • 36. cachebigquery $newquery = popular_posts_panic(3); if ( $newquery !== '' ) { if ( $newquery->have_posts() ) { while ( $newquery->have_posts() ) { $newquery->the_post(); ?> <h4><?php the_title(); ?></h4> <?php the_excerpt(); ?> <?php } wp_reset_postdata(); } }
  • 37. cachebigquery function renew_popular_posts() { for ( $i = 0; $i < 50; $i++ ) { if ( false === ( $popular = get_transient( 'popular_posts' . $i ) ) ) { delete_transient( 'popular_posts' . $i ); $query = new WP_Query( array( 'orderby' => 'comment_count', 'posts_per_page' => $i ) ); set_transient( 'popular_posts' . $i, $query, 60*60*24*365 ); } } } if ( !wp_next_scheduled( 'renew_popular_posts' ) ) { wp_schedule_event( time(), 'hourly', 'renew_popular_posts' ); }
  • 38. TOP OF HACKER NEWS CONQUERED
  • 41. expiry&garbagecollection ✓ everything works on request ✓ expired != deleted, unless requested ✓ unrequested, undeleted transients stay until you remove them explicitly
  • 42. scalarvalues ✓ accepts scalar values (integer, float, string or boolean) & non-scalar serializable values (arrays, some objects) ✓ SimpleXMLElement will FREAK. OUT., so convert it to a string or array of objects (i.e. simplexml_load_string)
  • 43. infinitetransients ✓ transients set without an expiration time are autoloaded ✓ if you don’t need it on every page, set an expiration (even if it’s a year) ✓ consider the Options API for non- transient data
  • 44. cachinggotchas ✓ in some shared hosting environments, object caching can be slower than using the database; check your host’s recommended settings ✓ always use the Transients API to access transients; don’t assume they’re in the database (or vice versa)
  • 46. usefultools TLC Transients Artiss Transient Cleaner Debug Bar Transients Supports soft- Deletes expired Adds panel to Debug expiration, transients and optimizes Bar with transient info background updating table