blog-banner

How to Alter Views Field Output Programmatically

  • Drupal 7
  • Drupal Planet
  • HOOK_VIEWS_PRE_RENDER()
  • Views

Drupal Views Alter Field Output

 

Amending the view output is no longer a tedious task. Especially by taking the advantage of settings available in Views 3.x like exclude from the display, style settings, rewrite results, and their sub-settings. The change can be anything simple from adding a <span> wrapper for CSS styling to complex token replacement (thanks to the token module for making the Views module more awesome).

 

[[{"type":"media","view_mode":"media_original","fid":"82","attributes":{"alt":"","class":"media-image","typeof":"foaf:Image"}}]]

 

Well, this works great most of the time, however, there are cases where you need a few lines of PHP code to make the output closer to the project's requirements. I hit upon such a case in my recent project. My requirement was to show the time difference from the expiry date (unixtimestamp) field. Something similar to what format_interval() API would return but in a different way.

 

The quickest and most tempting solution would be to enable Drupal core's PHP filter module and add a code snippet from the Views admin interface. At first look, this might look simple and hassle-free as you don't need to write any module but seriously this is not a Drupal way of doing it. To learn in-depth about why you should avoid PHP filters see https://drupal.stackexchange.com/questions/2509/what-are-the-downsides-of-using-custom-php-code-in-blocks-nodes-views-args

 

I Googled for views API documentation and came across hook_views_pre_render(). After a few attempts of failure, I figured out the way it works. I have a product node that has an expiry field. In the view output, I need to show the remaining time in terms of the number of days, hours, minutes, and seconds left before expiry. 

A quick module that implements hook_views_pre_render() did the trick. All it requires is a few lines of code as below,

  1. /**
  2.  * Implements hook_views_pre_render().
  3.  */
  4. function kf_products_views_pre_render(&$view) {
  5. $products_view = array('products', 'expired_products');  
  6. $results = &$view->result;
  7. foreach ($results as $key => $result) {
  8. if ($view->name == 'products') {
  9. $field_expiry_date = $result->_field_data['nid']['entity']->field_deal_expire;
  10. $expiry_date = _kf_products_get_remaining_time($field_expiry_date['und'][0]['value']);
  11. $results[$key]->field_field_deal_expire[0]['rendered']['#markup'] = $expiry_date;
  12. }
  13. }
  14. }

 

Ideally the code above loops through the result items of view and overrides the field_deal_expire value with a value returned by a custom function _kf_products_get_remaining_time().

 

The function _kf_products_get_remaining_time() returns a string value and it resembles as below,

  1. function _kf_products_get_remaining_time($expiry_date) {
  2. $remaining = '';
  3. $diff = $expiry_date - REQUEST_TIME;
  4. $days = floor($diff / 86400);
  5. $hours = floor(($diff - ($days * 86400)) / 3600);
  6. $minutes = floor(($diff - ($days * 86400) - ($hours * 3600)) / 60);
  7. $seconds = floor($diff - ($days * 86400) - ($hours * 3600) - ($minutes * 60));
  8. if ($diff > 86400) {
  9. $remaining .= $days . ' d ';
  10. }
  11. if ($hours > 0) {
  12. $remaining .= $hours . ' h ';
  13. }
  14. if ($minutes > 0) {
  15. $remaining .= $minutes . ' m ';
  16. }
  17. if ($diff < 86400) {
  18. $remaining .= $seconds . ' s ';
  19. }
  20. return $remaining;
  21. }

Besides page and block display, this trick works for additional displays like CSV and XLS file export featured by other modules like Views data export.

Get awesome tech content in your inbox