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 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 token module for making the Views module more awesome).
Well, this works great most of the times, however there are cases where you need a few lines of PHP code to make the output closer to 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 it in a different way.
I Googled for views API documentation and came across hook_views_pre_render(). After a few attempts of failure I figured the way it works. I have a product node that has expiry field. In the view output I need to show the remaining time in terms of 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,
Ideally the code above loops throught the result items of view and overriddes the field_deal_expire value with value returned by a custom function _kf_products_get_remaining_time().
The function _kf_products_get_remaining_time() returns a string value and it resembels as below,
function _kf_products_get_remaining_time($expiry_date){
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.
Thank you for this post sivaji! It actually helped me get over a hurdle in trying to understand how to replace the value of a field in a view with a calculated value. I've been able to get everything to work with my use case, except creating a variable ($interest_rate) that should be available from all nodes represented in the view. The variable assigned in the content type is field_mortgage_rate. The rate values are displaying in the View itself, so I'm confident the data is there. But all this seems to be doing is returning an $interest_rate value = 0.
Any suggestions or information you can provide to get this to work correctly?
Thanks sivaji! It didn't work at first, but then I tried field_mortgage_rate instead of field_field_mortgage_rate and it worked like a charm! Thanks for your help!My next challenge is to grab an input value from a Views exposed filter. Have you done anything along those lines?
Thanks for the reminder about how pre_render works. This function will be more efficient if you check for which view it is before looping through the values. <code> function kf_products_views_pre_render(&$view) { if ($view->name == 'products') { foreach ($view->result as $key => &$result) { $field_expiry_date = $result->_field_data['nid']['entity']->field_deal_expire; $expiry_date = _kf_products_get_remaining_time($field_expiry_date['und'][0]['value']); $result->field_field_deal_expire[0]['rendered']['#markup'] = $expiry_date; } } } </code>
Just in case for anyone who runs across this, he's correct. If you're trying to use hook_pre_render to modify your results, it won't work if you're rendering entities (like a node in a display mode). You'll have to use hook_views_post_execute instead.
Not sure why you created $products_view = array('products', 'expired_products');
Perhaps you were going to use if (in_array($view->name, $products_view)) as your criteria instead of if ($view->name == 'products') ... but I've learned NOT to assume anything when it comes to Drupal.
So is $products_view meaningful, or just a code 'left-over' that I can ignore?