---
title: "How to properly use PHP on Drupal views fields · Appnovation"
url: "https://www.appnovation.com/insights/how-properly-use-php-drupal-views-fields"
description: "When your view needs custom markup based on results, here's how to properly use PHP in Drupal Views fields without breaking things."
---

Article

# How to properly use PHP on Drupal views fields

[![](https://cdn.sanity.io/images/ey850001/production/819fd9428bb52162039d58049501bcc4ccc296d9-68x68.jpg?w=68&auto=format) manuel manuel Senior Drupal Developer](/people/manuel-manuel.md) Dec 08, 2014  
 4 min read 

![How to properly use PHP on Drupal views fields](https://cdn.sanity.io/images/ey850001/production/b6651d772602a892b9b983c305cea20af1ab2439-1400x400.jpg?w=1400&auto=format) 

Every once in a while, as a [Drupal website developer](/services/drupal-development.md) you will come across this problem. The view is working perfectly, you are almost there, but wait, the specification calls for this special piece of markup that well, is different depending on what results you are displaying, or might display nothing at all sometimes, etc. Not a problem you think, I'll just shove some PHP in!

The problem with this is that you break views caching and you are saving executable code as configuration. Not something that will make your colleagues, nor your client happy at all. Not to worry, there are better ways!

So, depending on what you need to do, views api has you covered. You can write an area plugin in case you need a dynamic header, footer, etc. You can also or define your very own field, and handle your special case that way. It sounds more daunting than it is. In this post I will explain how to provide your own custom field to views.

For example, a field which will check if the rest of the fields in the current row are populated, and if any of them are empty, then display a link markup to prompt the editor to take care of that.

OK, so first things first, our module will be called *appnovation\_fillout\_viewsfield*, and we need to let views know that we will be providing functionality, and where, so in our appnovation\_fillout\_viewsfield.module file we just write:

\<?php /\*\* \* Implements hook\_views\_api(). \*/ function appnovation\_fillout\_viewsfield\_views\_api() { return array( 'api' => 3, 'path' => drupal\_get\_path('module', 'appnovation\_fillout\_viewsfield') . '/views', ); }

This tells views that our files for it will reside inside the views directory under our module's directory. Easy.

Next, we'll tell views that we have a new field, and for which table our field is available. We do this by implementing [hook\_views\_data (opens in new window)](https://api.drupal.org/api/views/views.api.php/function/hook_views_data/7). Note that there is also [hook\_views\_data\_alter (opens in new window)](https://api.drupal.org/api/views/views.api.php/function/hook_views_data_alter/7), which you could use to replace an existing field with your new field, like for example, if you wanted to append the author to EVERY node title displayed by views or something crazy like that. Our field will be used with the node table, so:

\<?php /\*\* \* Implements hook\_views\_data(). \*/ function appnovation\_fillout\_viewsfield\_views\_data() { $data = array(); $data\['node'\]\['fillout'\] = array( 'title' => t('Fillout field'), 'help' => t('Will display a link to node edit ONLY if any of the current row\\'s listed fields is empty.'), 'field' => array( 'handler' => 'appnovation\_fillout\_viewsfield\_handler\_fillout', ), ); return $data; }

Note that our handler is called 'fillout', so the array is keyed appropriately. Also the handler is named as MODULE\_handler\_HANDLERNAME.

Great, so let's actually write the handler that provides the field. Create a file called appnovation\_fillout\_viewsfield\_handler\_fillout.inc inside our views directory, which will be picked up by views:

\<?php /\*\* \* @file \* Definition of appnovation\_fillout\_viewsfield\_handler\_fillout. \*/ /\*\* \* Provides a field which will display a link to edit the node if any other listed fields are empty. \*/ class appnovation\_fillout\_viewsfield\_handler\_fillout extends views\_handler\_field\_node\_link\_edit { /\*\* \* Override views\_handler\_field\_node\_link\_edit::render\_link() \*/ function render\_link($node, $values) { // Get all field handlers on this display $fields = $this->view->display\_handler->get\_handlers('field'); // Check if ANY field is empty foreach($fields as $key => $field) { // ignore our field (duh) if ($key !== 'fillout') { if (empty($field->get\_value($values))) { // Let the views hanlder provide the link, it checks for access etc ;) return parent::render\_link($node, $values); } } } } } 

Since we only provide an edit link, we'll just extend *views\_handler\_field\_node\_link\_edit* handler, which is battle tested and provides the necessary access checks, etc. We only have to check the rest of the display's field values for the row, and if we find any that are empty, then we call the views handler for the link, return it, done!

That's it. Very few lines of code, and a lot of functionality, thanks to views OO approach. Not only is this much cleaner and easier to debug, but you can also reuse the same code across all other views on the site, and easily include it on other future projects! So next time you think about inserting PHP in a view, take a minute to think about how to go about it using this approach - and share the code!

[![](https://cdn.sanity.io/images/ey850001/production/819fd9428bb52162039d58049501bcc4ccc296d9-68x68.jpg?w=68&auto=format) manuel manuel Senior Drupal Developer · Appnovation](/people/manuel-manuel.md) 

## Keep reading

[![What is Sovereign AI](https://cdn.sanity.io/images/ey850001/production/a5889abdd5e80376912546622e046e3fbef234b4-2496x1664.png?w=640&auto=format)](/insights/what-is-open-source-sovereign-ai.md)

 Article · 7 min AI 

### [What Is Open Source, Sovereign AI?](/insights/what-is-open-source-sovereign-ai.md)

Every company is encouraging more AI, and almost every AI bill is climbing. Sovereign AI is about two kinds of control: over your data and over your costs. Here's why open source sits at its foundation.

[Iain MacNeil](/people/iain-macneil.md) Article 

[![AI-first experience design](https://cdn.sanity.io/images/ey850001/production/8bbc2418e87924ef10f36115478a2e10d5bed95e-1584x624.jpg?w=640&auto=format)](/insights/how-build-ai-first-experience-without-throwing-out-everything-youve-already-built.md)

 Article · 6 min AI Sep 10, 2026 

### [How to Build an AI-First Experience Without Throwing Out Everything You've Already Built](/insights/how-build-ai-first-experience-without-throwing-out-everything-youve-already-built.md)

Users now expect a direct answer, not a list of links to click through. Here's how organizations can layer an AI-First experience onto their existing website or app, in weeks rather than years.

[Andrew Douglas](/people/andrew-douglas.md) Article 

[![What Becomes Possible When AI Can Read All the Data](https://cdn.sanity.io/images/ey850001/production/c28ab0bd26753421ee42937e13adc7a7f19b47f0-1296x510.jpg?w=640&auto=format)](/insights/what-becomes-possible-when-ai-can-read-all-data.md)

 Article · 4 min AI Sep 09, 2026 

### [What Becomes Possible When AI Can Read All the Data](/insights/what-becomes-possible-when-ai-can-read-all-data.md)

Most of the world's data has never been analyzed, only sampled. AI changes that. How AI-ready data platforms unlock questions no one could ask before.

[Appnovation](/people/appnovation.md) Article 

## Get the thinking,  
*before everyone else.*

One considered email a month. New essays, field notes from live engagements, and the occasional strong opinion. No noise.
