I am currently developing a theme where I want to add two permalinks.
One is redirecting to the index.php with some custom parameters and values (rule stored in the wp_options table), the other is redirecting to a file in my template which offers the admin-ajax.php functionality (rule stored in .htaccess file).

add_action( 'init', 'custom_rewrite_rules' );
function custom_rewrite_rules() {

        str_replace( ABSPATH, '', dirname( dirname( __FILE__ ) ) . '/api/ajax-api.php' )

    flush_rewrite_rules( true );
} );

As I am in developement mode I am flushing the rules by executing on the 'init' hook as well
(I know this is bad practice but this seems to be the best method for me to check if there is any change in the .htaccess file.).

The Problem:
Even though flush_rewrite_rules() resets hard flushing by default I set the parameter to true just to make sure. My first rewrite rule is perfoming very well whereas the .htaccess file is not regenerated until I visit the options-permalink.php page in the backend (where the flush-function is called as well and works?!).

I already tried excecuting flush_rewrite_rules() on another hooks as proposed in the Reference.

Thanks in advance for your help!

Even changing the code to the following did behave the same way…

global $wp_rewrite;
$wp_rewrite->add_rule( '^(activate|reset)/([0-9]*)sfa([A-Za-z0-9]*)/?$', 'index.php?sfa_user=$matches[2]&sfa_password_reset=$matches[3]', 'top' );
$wp_rewrite->add_external_rule( 'ajax-api/?$', str_replace( ABSPATH, '', dirname( dirname( __FILE__ ) ) . '/api/ajax-api.php' ) );
$wp_rewrite->flush_rules( true );
  • What is the point of .htaccess when you can use WP Rewrite api for that?
    – Ismail
    Commented Mar 17, 2017 at 12:45
  • @samuel What do you mean? flush_rewrite_rules() uses WP_Rewrite::flush_rules(). There should be no difference, should there?
    – cruzquer
    Commented Mar 17, 2017 at 13:15
  • @adrianwell, I do face the same problem now. Can you tell me how did you fix this issue by using save_mod_rewrite_rules(). I dont have enough credits to add comments, so please bear with me this question.
    – Nidhin
    Commented Feb 14, 2018 at 5:28

3 Answers 3


Try using this for the the rewrite:

global $wp_rewrite;
$wp_rewrite->flush_rules( true );

see if that will work.

  • 2
    why should it make any difference? Commented Mar 17, 2017 at 16:17

Seems like you are confusing the internal rewrite rules, which should have been called "parsing rules", with htaccess rewrite rules. They are not the same and in general do not function the same way.

Your first rule is a parsing rule, the second is a rewrite rule which

  1. should not be done at all. Accessing directly a php file is a no-no for several reasons, even if you mask it in some way.

  2. You need the htaccess generation hook, which as you observed correctly will be triggered only on the permalink page, or you will have to trigger the generation in your code. since this is bad idea due to point 1. and it will not work in multisite, I feel justified in being lazy and not digging the names of the function call and hook ;)

  • Ok besides the fact that you think it is not a good idea to link to a php file you say that rewrite rules do not belong to the add_rewrite_rule() function itself because it kind of confuses the flush_rewrite_rules() function. This is kind of tricky as flush_rewrite_rules() basically should be able to handle every kind of rule, right? And as the rewrite rule is added to the .htaccess file when opening the permlink settings it shows that add_rewrite_rule() itself is generaly capable of adding rules.
    – cruzquer
    Commented Mar 17, 2017 at 17:43
  • I would really appreciate if you could name some reasons why this is generally a bad idea :) thanks.
    – cruzquer
    Commented Mar 17, 2017 at 17:44
  • no, as I said wordpress rewrite rules are just to be able to extract the "common" parameters wordpress uses to identify content, in other words the post number, author id, etc. They are not general "use this file for that url" rules. Commented Mar 18, 2017 at 5:15
  • Accessing directly .... 1. You do not know where the wp-config.php file is located which mean you will not be able to reload wordpress to do anything. This is tricky as in simple install it will work, but there are enough people that do not run simple installs and put themes and the config file in unexpected places. Access to anything in the themes directory should be blocked by any security aware host although I am not sure if this will apply to what you want to do. Commented Mar 18, 2017 at 5:20
  • I see what you mean. But as I am selling websites to my clients and not themes in general it is not a problem for me, even though I am one of those you mentioned who try to relocate and rename the wp-content, theme, media, wp-config files and folders. The only files I point to directly are located in my theme folder which path I can generate as I’ve done in the code.
    – cruzquer
    Commented Mar 18, 2017 at 8:25

Finally I found the solution… save_mod_rewrite_rules() is the function which will generate and add rewrite rules. In the Doc it says:

/* If the function named 'save_mod_rewrite_rules' exists, it will be called. */

This function is part of wp-admin/includes/misc.php which is loaded by wp-admin/includes/admin.php which is loaded right before the admin_init action hook.

Nevertheless you should never flush rewrite rules at any init action hook: Flush Rewrite Examples

Your Answer

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

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