Moodle settings and performance

Did you know that every settings.php file in every plug-in gets loaded on pretty much every page load as the Settings block sorts itself out?

I didn’t, but Sam Marshall pointed it out to me when I put a database query in one of my plug-in’s settings page and he found that the query was running all the time.  You can test it for yourself – just echo ‘running’; in your file and browse your site.

One easy way round this is to wrap your settings definitions and database queries in an if ($hassiteconfig) check which means that they only run for users with the moodle/site:config capability.  In most sites that’s going to be a pretty small pool of people and maybe you don’t care about them suffering slightly slower page load times.

But what if you do care because your query is horrid?  Or just want to do it ‘properly’?

Yesterday I was asked to add a new setting to one of my local plug-ins which provides a list of courses to our search engine spider so it knows what is worth indexing.  The new setting is to restrict so that some entire categories are excluded.

Oh dear … how do I get the list of categories into a multi-select config setting without a DB call?

Luckily Tim Hunt knew the answer and in the spirit of sharing, and hopefully me not forgetting, I’m going to write about it here!

  1. Make a new file in your plug-in, I suggest calling it settingslib.php.  In here you will define a new admin_setting_config class.  Tim said you can’t do it in settings.php directly (even though its a small class) because settings.php gets loaded twice and you’d get errors about declaring classes which already exist.  However, I just tried it and it seemed to work OK, so I’m not sure about that.  However, in the interests of tidiness, a separate file for a new class is no bad thing.
  2. Create a new class in settingslib.php with a meaningful name including your plug-in’s location and name and something logical about what this class is doing.  Set it to extend the existing admin setting class that you want to use to display your form field.
  3. In your class override the load_choices() function to do the database lookup and then return the choices in the way your parent admin setting class is going to expect.  For multi-select this is an array.

So my entire class looks like this:

class local_fs_admin_setting_cats extends admin_setting_configmultiselect {
  public function load_choices() {
    global $DB;
    if (is_array($this->choices)) {
      return true;
    }
    $this->choices = $DB->get_records_menu('course_categories', 
                          array(), '', 'id, name');
    return true;
  }
}

To use your new class, you instantiate it in the same way you normally would in settings.php, but pass null for the $choices parameter.  So mine looks like this:

 $settings->add(new local_fs_admin_setting_cats(
                'local_federatedsearch/searchcategories',
                get_string('searchcategories', 'local_federatedsearch'),
                get_string('searchcategoriesdesc', 'local_federatedsearch'),
                array(), null));

We think (by git blame) that thanks go to Petr Skoda for implementing the lazy loading ability for admin settings that makes all this possible.

1 comment
  1. Tim Hunt said:

    Thanks for writing this up Jenny. I wish more people know about this.

Follow

Get every new post delivered to your Inbox.

Join 272 other followers

%d bloggers like this: