I am new to drupal and basically I made a database within drupal and filled it with some dummy data. I want create/format/populate a table that looks like on one of my drupal pages:

| Resource  |          Week1          |          Week1+7          |    TOTALS     |
| resource1 | Hours(Week1, resource1) | Hours(Week1+7, resource1) | totals across |
| resource2 | Hours(Week1, resource1) | Hours(Week1+7, resource2) |               |
| TOTALS    | totals above            | totals above              |               |

I understand that you do it through views and I was trying to do it by creating my own module using the views_data() hook to try to create it (using http://mydons.com/how-to-expose-custom-module-table-to-views-in-drupal/ as a base/resource). I am kind of stuck though and I have no idea what the best approach would be to start to create a table that looks like the above. I am not sure this is the correct way/best way to do it and any direction/tips you guys can help me out with would be great.


  • I need some more info to provide a good answer. Do I understand it correctly that you want to use a standard and external SQL table within Drupal and create, read, update and delete data in that table? How many rows are you expecting to store in the end in that table? And are you required to hold that data in an external table as opposed to store it in Drupal? BR / Fredrik
    – drupwell
    Mar 11, 2014 at 19:04

3 Answers 3


You can create a custom table to display whatever data you want in a custom module by building the information output in a function, first you have to implement HOOK_menu for defining you path for the page containing the table and afterwards implementing the callback function for that page. I'll give you a real example here:

* Implement hook_menu().
function HOOK_menu() {
  $items = array();

$items['admin/config/my_table'] = array(
      'title' => 'My Table Page',
      'description' => '',
      'page callback' => 'my_table',
      'access arguments' => ....,

 return $items; 

As you can see i have my path and the callback is defined to the function my_table. Let's create that as well

function my_table {

    // Create table header 
    $header = array(
        array('data' => t('COLUMN 1')),
        array('data' => t('ANOTHER ONE')),
        array('data' => t('COLUMN EXAMPLE')),
        array('data' => t('BLA BLA'))

   .... // create table rows

    $output = '<div class="description">';
    $output .= '<p>' . t('Say whatever you want to appear'). '</p>';
    $output .= '</div>';

    // here we render the actual table
    $output .= theme('table', array('header' => $header, 'rows'=> $rows, 'attributes' => array('id' => 'something') ));

    // and return the html output to our page
    return $output;


Hope this helps! Cheers!


Well, exposing the data of your table to views and then fetching and displaying it as table using views formatter is a good option, but if this is all you need ( I mean no complex use cases like filtering sorting and stuffs like that) it will be overkill in my opinion.

I think you can use the awesome database API of Drupal to fetch the content and probably render it using theme_table() which will give you the output as table. Please check the doc and examples to make sure you are passinf the data to theme_table() in proper format. there are lots of example codes available. just google it.


If you want to take advantage of render caching return a render array. Unfortunately I have not found a good blog post of this subject. Documentation on drupal_render(); read up on the #cache section, easiest way to speedup your site is by caching. I use they keys in my own code as the table code we use uses dates so I have an array of dates that I pass into the "keys" key of the "#cache" key. Example below just uses a simple 1 hour global cache. The trick with the cache is using the #pre_render function, we use it to fill in the $rows; the actual render function (in this case theme_table()) will build the table given the header and rows. Also note that I'm adding in CSS by using the #attached key; this is the standard way to do it in Drupal 8 so it's future proof. If the cached data exits, then pre_render function does not get called. drupal_render will take care of caching for us.

function my_code_table_render_array() {
  // Define table header.
  $header = array(
    'resource' => 'Resource',
    'week1' => 'Week1',
    'week1_7' => 'Week1+7',
    'totals' => 'TOTALS',

  // Build table render array.
  $table = array(
    '#theme' => 'table',
    '#pre_render' => array('my_code_pre_render_function'),
    '#header' => $header,
    '#attributes' => array('class' => array('table', 'table-striped')),
    '#attached' => array('css' => array(drupal_get_path('module', 'my_code') . '/my_code.css' => array('type' => 'file'))),

  // Cache this for 1 hour.
  $table['#cache'] = array(
    'expire' => REQUEST_TIME + 3600,

  return $table;

function my_code_pre_render_function($elements) {
  $rows = array();

  // Put the rows from the database in the rows array. 
  // This will change depending on your data structure.
  foreach ($query_result AS $key => $values) {
    $rows[$key][] = array(
      'data' => 'Data from the database',
      'title' => 'Extra data shown on mouse hover',
      'class' => $array_of_classes,

  $elements['#rows'] = $rows;
  return $elements;

If using multiple render arrays you can return an array of the render arrays like so. The order of the arrays determines the order of the output.

function my_code_form_table_render_array() {
  $input_form = drupal_get_form('my_code_input_form');
  $table = my_code_table_render_array();
  $page_array = array($input_form, $table);
  return $page_array;

In both examples we would set "page callback" to "my_code_table_render_array" OR "my_code_form_table_render_array" in your own hook_menu() hook.

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.