From the early days, Drupal had the ability to embed PHP code in its content. This provides flexibility and functionality, most importantly, nodes and blocks can contain dynamically fetched data from the database using custom queries and displayed them in other content.

This is an easy approach to get such data without writing a module. All you need to do is assign the PHP input format filter to the node or block and paste your PHP code in it, and voila, you have dynamic content.

Code in Content: the issues

However, this approach is suboptimal and has serious drawbacks, including:

Lack of Readability and Clarity

Since the code is embedded within pieces of otherwise HTML content, it is not obvious where the code is, so tracking it is really hard. Moreover editing it in a textarea is far less friendly than in a prope text editor with syntax highlighting. This leads to maintenance issues with this code in the long run.

Potential Security Issues

Since the code is not readily visible, it is more prone to be missed in doing code reviews or security audits, than if it would have been in a more conventional repository. This is why modules such as Paranoia exist, and why Drupal 6 now has a separate PHP module that has
to be explicitly enabled in order to get the PHP filter functionality.

Lack of Version control

Nodes and blocks are never put in a versioned code repository, such as CVS, SVN or GIT. Because of that tracking changes is very hard, and maintenance can be a nightmare.

Performance Drawbacks

Code stored in the database is first fetched from the database, then executed by PHP. Because of that, this code is never cached by accelerators/op-code caches, and can be slower to execute than cached code.

Search Implications

Embedding PHP output within Drupal's search provides some interesting challenges.

As you can see, there are several drawbacks here.

Views is another module that stores pseudo-code in the database (actually query generator instructions). However, views offer the ability to export its queries as PHP code which can be made into modules and suffer none of the above drawbacks.

Removing Code from Content

For the above reasons, we went on a mission over the past few weeks to rid sites of code embedded in content. So far, we have done 5 sites, the last of which is itself.

The process is described as follows:

Get A List of all PHP Content

First find out what is your PHP filter format ID. You can do this via the following SQL.

mysql> SELECT * FROM filter_formats;
| format | name          | roles | cache |
|      1 | Filtered HTML | ,1,2, |     1 |
|      2 | PHP code      |       |     0 |
|      3 | Full HTML     |       |     1 |

Now, we know that 2 is the PHP filter format.

Next we estimate how many PHP nodes we have.

SELECT n.format AS id, COUNT(*) as cnt 
FROM node_revisions n 
WHERE format = 2 
GROUP BY n.format;
| id | cnt |
|  2 | 14 |

And then we get the text of the nodes that have PHP in them, so can work on making it into modules. Note that some nodes may have the PHP format, but not PHP code in it, e.g. when you need to paste javascript verbatim.

SELECT nid, body FROM node_revisions WHERE format = 2; 

And then the blocks too. Again, not all the blocks may contain actual PHP code.

SELECT * FROM boxes WHERE format = 2; 

After that, we need to find blocks that have PHP visibility settings too, although the body may not have PHP:

FROM blocks b INNER JOIN boxes x ON = 
WHERE status = 1 AND pages LIKE '%<?php%'; 

Now we have all the info we need, we then move to analysing it.

Do Some Analysis

Study each node and block and see whether you can use the code as is, or make it simpler as you refactor it and move it out from content to modules. This all depends on the actual code and what it does.

Convert Blocks into Modules

A basic block module will look like this, which should go in a file called something.module:

function something_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
$blocks[0]['info'] = t('Some block');
return $blocks;
case 'view':
$block['subject'] = t('Some block');
$block['content'] = something_output();
return $block;
function something_output() {
// code goes here
return $output;

All you need is an file to go with it, and you are all set.

Whether you combine several blocks in one module or keep it separate depends on your particular specifics.

Convert Dynamic Node Data into hook_nodeapi

Now, you need to convert the code that was in nodes to become modules. You can chose to combine several nodes in one module so as to reduce the number of modules on your site.

On, most nodes were there to preserve a place in the Handbook hierarchy, and provide dynamic data in them. In this case, we need to keep the specific nodes as they are, but change their format from PHP to Filtered HTML.

Then we have a module like the one below that appends the dynamic content at the end of the node body. 

function something_nodeapi(&$node, $op = 'view', $teaser = FALSE, $page = FALSE) {
if ($op == 'view' && $page) {
$extra = '';
switch ($node->nid) {
case 48380:
$extra = something_output();
case 257382:
$extra = something_other();
$node->content['body']['#value'] .= $extra;
function something_output() {
// code goes here
return $output;
function something_other() {
// code goes here
return $output;

Of course, you need an info file to go with the above module as well.

Convert Views into Modules

Using the export function of views, you should convert the views into modules. Check the views documentation for more info.

Now you have the code versioned, visible, auditable, faster and more maintainable. You can sleep better now ...



Is your Drupal or Backdrop CMS site slow?
Is it suffering from server resources shortages?
Is it experiencing outages?
Contact us for Drupal or Backdrop CMS Performance Optimization and Tuning Consulting