How to optimize on-the-fly theme switching for mobile browsers?

First of all, you should know that $_SERVER['HTTP_USER_AGENT'] is not fully reliable because its output is based on http request User-Agent header, and so it can be easily omitted or disguised.

That said, sure your method will detect the majority of mobile requests, but be aware the mayority is not totality.

Now, you know that current theme is based essentially on a option: template (and if you have active a child theme the option is stylesheet). This option contain the slug of the theme (normally the theme folder name).

What switch_theme does is updating that option, so runs a query on database. In addition, you need to also run that function even if the default theme (setted in admin) is the non-mobile and the request is from non mobile.

The optimized solution is to use the shortcut filter for options: "pre_option_{$option}", that is fired before any option is getted, and if the function hooked there returns a non false value that value is returned without any database query.

That brings 2 advantages:

  1. you don’t need to run any db query when need to output the non-default theme
  2. you don’t need to do anything when need to use the default theme

The code is pretty easy, just 3 lines:

if( wp_is_mobile() ) {
    add_filter( 'pre_option_template', function() { return 'theme_mobile'; } );
    add_filter( 'pre_option_stylesheet', function() { return 'theme_mobile'; } );
} 

I’ve used wp_is_mobile function for sake of semplicity, it’s not 100% reliable, but how said in first lines, nothing using $_SERVER['HTTP_USER_AGENT'] is 100% reliable.

Please note that:

  1. if the mobile theme is a child theme (and parent theme is the same for both mobile and not mobile) you must use the only 'pre_option_stylesheet'
  2. my code require PHP 5.3+ due to the usage of a closure