add_role() run only once?

I was surprised to discover that add_role() modifies the database and fails if the role already exists. There are two implications here, one first more serious than the other: 1) if you’re in development and update your add_role code, you must first remove_role() 2) once you have it right, you should never have to run that code again.

So typically I have been putting my add_role() inside a wp_loaded action hook. And since I’m in development, I’ve also added a remove_role() before my add_role so I can be sure that if I modify my list of caps, it will actually take effect.

Read More

But clearly this is now being run every time a page of the blog is being accessed. Okay, I could put it in an admin-only action, or I could create a plugin page maybe under Users or Tools where this role can be created once. I guess I’m hoping there’s a simpler, more elegant solution out there.

I don’t imagine there’s a run_once kind of action is there?

Or is the best practice just to add the role and then use add_cap() a bunch of times? And even then I imagine add_cap is accessing the db.

Just thinking in terms of the best way to reduce unncessary db access. What are your best practices?

Related posts

Leave a Reply

1 comment

  1. The user roles and capabilities are saved in the database so once you have you have used add_role() its saved and then next load WordPress will know that role just like the built in roles.

    Now if you look at the function add_role() more specifically at line 141 you will see that it only saves the role and capabilities in the database if the var $use_db is set to true (which he is by default) so you can simply change it before you call your add_role() function and the role won’t be saved.

    try:

    //globalize $wp_roles
    global $wp_roles;
    //set use_db to flase
    $wp_roles->use_db = false;
    //then add your role
    $wp_roles->add_role( $role, $display_name, $capabilities );
    

    Update:

    If its in a test/development environment then i see no downside, but if you are on a live environment then you save the time it take to create that on role every load.

    As for best practice run once, if in a plugin you should use register_activation_hook and for any thing else i use a simple custom made conditional function:

    function run_once($key){
        $test_case = get_option('run_once');
        if (isset($test_case[$key]) && $test_case[$key]){
            return false;
        }else{
            $test_case[$key] = true;
            update_option('run_once',$test_case);
            return true;
        }
    }
    
    **usage:**
    if (run_once('add_user_role')){
        //do you stuff and it will only run once
    }