3

I'm creating a module that is basically a form but needs to use information from a table in the database to react the some of the button presses. Rather than executing the database query each time the button is pressed in the callback function, is there a way to retrieve all of the information from the database when the module loads and store it in a variable so that other functions in the module can use/access it?

Thanks in advance

Code: An example module that is similar to my current one. I need to use results from the database query in the copy_text function, and as I build the form up the same results in the callbacks for the other functions, so I don't see a point in putting the same db_query in each callback - surely that's just unnecessary querying of the database:

<?php


function playground_menu() {
  $items['playground/form'] = array(
    'title' => 'Form',
    'description' => '',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('playground_demo_form'),
    'access arguments' => array('access content'),
  );
  return $items;
}

function playground_demo_form($form, $form_state) {

  $form['input'] = array(
    '#type' => 'textarea',
    '#title' => t('Input text'),
    '#prefix' => '<div id="in-text">',
    '#attributes' => array(
      'placeholder' => t('Enter some text here... '),
    ),
    '#suffix' => '</div>',
  );

  $form['buttons'] = array(
    '#type' => 'fieldset',
    '#title_display' => 'invisible',
    '#attributes' => array(
      'style' => 'border: 0px; text-align: right',
      'class' => array('container-inline'),
    ),
  );

  $form['buttons']['copy'] = array(
    '#type' => 'button',
    '#value' => 'Copy text',
    '#ajax' => array(
      'callback' => 'copy_text',
      'wrapper' => 'out-text',
//          'method' => 'replace',
//          'effect' => 'fade',
    ),
  );

  $form['buttons']['reverse'] = array(
    '#type' => 'button',
    '#value' => t('Reverse text'),
  );

  $form['buttons']['clear'] = array(
    '#type' => 'button',
    '#value' => t('Clear text'),
  );

  $form['output'] = array(
    '#type' => 'textarea',
    '#title' => t('Output text:'),
    '#prefix' => '<div id="out-text">',
    '#value' => '',
    '#attributes' => array(
      'placeholder' => t('Your text will appear here...'),
    ),
    '#suffix' => '</div>',
  );

  return $form;
}

function copy_text($form, $form_state){
  $form['output']['#value'] = $form_state['values']['input'];
  return $form['output'];
}

2 Answers 2

2

You could just wrap your query in cache test, like this:

function steam_get_username2($steam64)  {
  if($cached = cache_get('steam'.$steam64, 'cache'))  {
    $username = $cached->data;
  }
  if(empty($username)) {
    $username = 'blank'; // Expensive code here
    cache_set('steam'.$steam64, $username, 'cache', 60*60); //1 hour
  }
  return $username;
}

Example by alandarev on Drupal.org, tweaked a bit by me.

Please remember that HTTP is stateless protocol, so each time callback is called, it's a new execution, with new variables. That's why Drupal can't cache to RAM on it's own. So Drupal caches in database. Unless your query is really complicated, caching it makes little sense - it only substitutes one query with another. You have to use APC or Memcached to really feel the difference, as these allows fast cache in RAM.


If you need the same data in few places during one call, like form building function, validators and callback function, then use static cache. &drupal_static($name, $default_value = NULL, $reset = FALSE) is what you need in such situations. Traditional way is to use it as

$function_static_data = &drupal_static(__FUNCTION__);

This will make sure static data is properly associated with function that uses it, freeing you from the burden of collision prevention (as function names are unique in PHP already).

2
  • If you want to include a bit about the static cache (even a link to drupal_static() would be fine) I can delete my answer, this covers things much better
    – Clive
    Commented Aug 4, 2014 at 14:01
  • @Clive I don't know if deleting your answer is needed, but I did my best to briefly describe static cache. Not with example, but it is not directly needed in OP's case, and there are examples in the docs anyway.
    – Mołot
    Commented Aug 4, 2014 at 14:15
2

You've got two options, depending on your needs

  1. Static cache - data is built once during a single request and re-used where needed. Your query will run once but once only on every related request. See drupal_static() for example usages.
  2. Backend cache - the results of your database query are cached, and you query the cache bins for the data instead of your database table. Your query will be run once only, until the cache is invalidated, when it'll obviously need to be run again. You'll still incur the overhead of querying the cache, so if your cache is database-based, this may or may not be worth it, depending on the size and complexity of your data. With this method you'll also need to think about how/when/if you invalidate the cache to get fresh data. See the Cache API docs for examples.
9
  • He is concerned about callback, so your 1. does not apply. Not in this specific case. (Noting this more for OP benefit than yours, of course)
    – Mołot
    Commented Aug 4, 2014 at 11:51
  • @Mołot The question is is there a way to retrieve all of the information from the database when the module loads and store it in a variable so that other functions in the module can use/access it?. The first option is far more appropriate for that (which is why I included it first), the 2nd option is a more complicated 'backup', that probably isn't what the OP is looking for. But either way, he's got both options now so can pick which suits his use-case
    – Clive
    Commented Aug 4, 2014 at 11:53
  • 1
    I'm not saying you should delete it. I just wanted to make sure OP will not think it will solve slow AJAX response issue if that query is called just once per callback. Anyway, it's a question about code, without code shown, and that's the source of our discussion now. So I'm leaving it as is, no more comments or anything from me here unless OP will add his code so we could see what he is really asking about.
    – Mołot
    Commented Aug 4, 2014 at 12:00
  • 1
    @Andy "caching" is just the catch-all word to describe the saving of data that can be retrieved at some point in the future...whichever of the above solutions will work for your use-case, you'll definitely be caching the data. You don't have to use Drupal's cache layer, but it would nuts not to since it's already implemented and working
    – Clive
    Commented Aug 4, 2014 at 12:50
  • 1
    Now, with code edited into question it seems I guessed properly. Of course wrapping it with static cache is virtually free, so it wouldn't hurt - but also wouldn't really help. Undeleting my answer as it wasn't a total miss.
    – Mołot
    Commented Aug 4, 2014 at 13:16

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.