6

I'm making a custom theme. It's a highly specialized theme to make WordPress into like an application rather than a CMS system or blog. For instance, a Dental Office Scheduling System (with CMS and widget capabilities), as an example.

Because my theme needs pretty URLs to work properly, something I really need is for the .htaccess file to be that default that gets created only when someone sets Permalinks to Custom (and then types in something like %postname%). How do I trigger that in WordPress, programmatically, so that it creates this? I mean, I could probably overwrite the file myself during theme activation, but the better thing would be to use the WordPress API for it.

2
  • "my theme needs pretty URLs to work properly" why? Dec 20, 2011 at 22:40
  • @ChristopherDavis because it's an app theme, not a regular theme. I have an MVC framework loaded inside a theme folder that operates heavily on rewrites.
    – Volomike
    Jan 10, 2012 at 3:49

3 Answers 3

9

To fully enable permalinks, you also need to ensure that .htaccess is also created. To do that, you need to set an option and flush the rules with a Boolean.

global $wp_rewrite; 

//Write the rule
$wp_rewrite->set_permalink_structure('/%postname%/'); 

//Set the option
update_option( "rewrite_rules", FALSE ); 

//Flush the rules and tell it to write htaccess
$wp_rewrite->flush_rules( true );

If you use this in a plugin, it needs to be in the init hook, not the load hook. If it's in the load hook, it will throw an error saying $wp_rewrite is null.

Important: You should also have a conditional so this is only set once. (You can create an option and check if it's set, if not then you run this permalink code and set that option)

I also typically check if it's the admin side and only run it if it is.

4
  • 2
    You should not flush rewrites on init, never. It is expensive and slows your page load times dramatically. Rewrite rules are saved in the db, so flushing rewrites on init means that there will be a lot of db calls to resave rewrite rules on every pageload Oct 22, 2015 at 6:00
  • @PieterGoosen Read the rest of my answer. What I do is I check if it's been set and only set it once (so when I first install the plugin) and it never runs again. I also check if it's is_admin() but that's not necessary if it's only run once.
    – Don Rhummy
    Oct 22, 2015 at 6:01
  • Add that info in your answer. That is important info that your answer need to make it more acceptable ;-) Oct 22, 2015 at 6:03
  • @PieterGoosen done. (Although I already had it in my answer except for the "is_admin()" piece)
    – Don Rhummy
    Oct 22, 2015 at 6:04
6
function change_permalinks() {
    global $wp_rewrite;
    $wp_rewrite->set_permalink_structure('/%postname%/');
    $wp_rewrite->flush_rules();
}
add_action('init', 'change_permalinks');

You may not need the action hook if you're sticking this in your theme activation function code.

I also found that this only slightly worked. You still have to click the Permalinks settings page for that .htaccess file to be created. So, what to do? Well, I found I could use an IFRAME that loads that page automatically for me from my theme's options panel, and then it would create that .htaccess file for me.

<iframe style="position:absolute;top:-5000px" src="<?= site_url() ?>/wp-admin/options-permalink.php"></iframe>
4
  • 3
    Calling flush_rules on the init action is a bad, bad idea. It might be acceptable in an activation or installation function call, but not on init.
    – Otto
    Aug 25, 2012 at 15:15
  • 1
    I know this is old, but you can get it to rewrite the ".htaccess" file by changing your flush rules to this: update_option( "rewrite_rules", FALSE ); $wp_rewrite->flush_rules( true ); This will write the ".htaccess" file.
    – Don Rhummy
    Oct 21, 2015 at 22:23
  • @DonRhummy please post it as an answer and I'll mark it as the new answer.
    – Volomike
    Oct 22, 2015 at 4:57
  • @Volomike i added the answer
    – Don Rhummy
    Oct 22, 2015 at 5:04
2

This is how I use this, to only occur when my theme is activated, and only if there is no pre-existing setting saved (to not break something done before my theme is used).

/*
 * Set permlinks on theme activate
 */
    function set_custom_permalinks() {
        $current_setting = get_option('permalink_structure');

        // Abort if already saved to something else
        if($current_setting) {
            return
        }

        // Save permalinks to a custom setting, force create of rules file
        global $wp_rewrite;
        update_option("rewrite_rules", FALSE);
        $wp_rewrite->set_permalink_structure('/news/%postname%/');
        $wp_rewrite->flush_rules(true);
    }
    add_action('after_switch_theme', 'set_custom_permalinks');

The advantage of this is that it will only run once when the theme is activated, not every time WordPress is loaded by a visit to the site.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.