Skip to main content
pseudo field in view

Drupal 7 - Exposing pseudo field in view from custom table


At KnackForge we often see requirement to expose custom fields to views for better integration with Drupal flow. In this article we are going to see steps to expose a custom field from a custom table. Infact its a virtual field. 

Use case:

Assume you have two custom fields total_marks and marks_obtained in a custom table. Now you need to calculate the percentage of mark scored. You don't need a field in table for this. You can create a virtual field bound to marks_obtained field.

Hooks to be used:

hook_views_data_alter() or hook_views_data()



I assume the custom table has already been created using .install file.


In your custom module write,

 * Implements hook_views_api().
function MY_MODULE_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'MY_MODULE') . '/views/',
this tells Drupal that we have some views related custimizations. Create a views folder under your module, with a file called,
 * Implementation of hook_views_data_alter().
function MY_MODULE_views_data_alter(&$data) {
  $data['CUSTOM_TABLE_NAME']['percentage'] = array(
      'title' => t('Percentage obtained'),
      'help' => t('Shows percentage obtained'),
      'real field' => 'marks_obtained',
      'field' => array(
        'handler' => 'MY_MODULE_views_handler_field_percentage',
        'click sortable' => TRUE,
      'argument' => array(
        'handler' => 'views_handler_argument_numeric',
        'name_field' => 'title',
        'string' => TRUE
      'filter' => array(
        'handler' => 'views_handler_filter_numeric',
        'help' => t('Filter results to a particular result set'),
      'sort' => array('handler' => 'views_handler_sort'),
The above defines our virtual field bound to marks_obtained field for use in views as a field.
* Implements hook_views_handlers()
function MY_MODULE_views_handlers() {
  return array(
    'info' => array(
      'path' => drupal_get_path('module', 'MY_MODULE') . '/views/handlers',
    'handlers' => array(
      'MY_MODULE_views_handler_field_percentage' => array(
        'parent' => 'views_handler_field',
Place a "handlers" folder inside MY_MODULE and write a file called
Inside that file write,
 * @file
 * Handles filtering by networks
class MY_MODULE_views_handler_field_percentage extends views_handler_field {
 function render($values) {
    $total_marks = $this->options['total_marks'];
    $marks_obtained = $this->options['marks_obtained'];
    $tokens = $this->get_render_tokens('');
    if(!empty($tokens)) {
      $total_marks = $tokens[$total_marks];
      $marks_obtained = $tokens[$marks_obtained];
      return ($marks_obtained/$total_marks) * 100;
   return 0;
  function option_definition() {
    $options = parent::option_definition();
    //define our custom settings fields
    $options['total_marks'] = array();
    $options['marks_obtained'] = array();
    return $options;
  function options_form(&$form, &$form_state) {    
    $options = array();
    foreach ($this->view->display_handler->get_handlers('field') as $field => $handler) {
      $options[t('Fields')]["[$field]"] = $handler->ui_name();
    $form['total_marks'] = array(
      '#type' => 'select',
      '#title' => t('Total marks'),
      '#options' => $options,
      '#default_value' => isset($this->options['total_marks']) ? $this->options['total_marks'] : '',
      '#required' => TRUE
    $form['marks_obtained'] = array(
      '#type' => 'select',
      '#title' => t('Marks obtained'),
      '#options' => $options,
      '#default_value' => isset($this->options['marks_obtained']) ? $this->options['marks_obtained'] : '',
      '#required' => TRUE
    parent::options_form($form, $form_state);

  function options_submit(&$form, &$form_state) {
    parent::options_submit($form, $form_state);
    //update our custom values
    $this->options['total_marks'] = $form_state['values']['options']['total_marks'];
    $this->options['marks_obtained'] = $form_state['values']['options']['marks_obtained']; 
options_definition() and options_form() method let us to define custom options for our field, in which we attach the previously included fields in view i.e total _marks and marks_obatined which are necessary for our field to work. It will show a select box where we can choose the fields that are available as views field.
options_submit() method lets us to get the submitted values. 
render() method is responsible for final result of the field. We use get_render_tokens() method to get available tokens for that row and get the total_marks and marks_obtained values. Then we return the final percentage.


Let me know, if you have any queries :)


Hi, As stated there, have you try adding files[]=views/ line? If the custom table has not been already exposed to views, you might need to use hook_views_data() to do so. For eg, function MODULE_views_data() { $data['clicktracking']['table']['group'] = t('Tracking'); $data['clicktracking']['table']['base'] = array( 'field' => 'click_id', 'title' => t('Click Tracking'), 'weight' => -10, ); $data['clicktracking']['table']['join'] = array( 'node' => array( 'left_field' => 'nid', 'field' => 'nid', ), ); ...then define the field..... Let me know if you need more details. Ref