Getting rid of Drupal's "PHP Filter" input format

Thu, 26/05/2016 - 10:54 -- James Oakley

Drupal 7 and below came with an optional module you can use in your input formats - the "PHP Filter". This allows you to put PHP code into the content of your webpages, and Drupal will process the PHP before rendering the page.

PHP Filter - a Bad Idea ™

Put like that, you're probably wondering why on earth anyone would want to do that. The content of a webpage, in a Content Management System (which is how Drupal is often used) should be just that - the content. Only in a manually coded site would you put the website logic (the server-side PHP) in the same place as your content.

Well, precisely. And there are other reasons why it's a bad idea.

1. Security. Any PHP code in a module can be run through various automated or manual checks to make sure you've written good, secure code. Maybe even your webserver runs tools that scan for possible signs of malware. PHP code in your content is buried deep in the database, where it won't get checked.

2. Debugging. If you find a page of your site is not working as it should, you need to identify where things go wrong. It makes the job a lot more complicated if there's PHP code in page content, as well as in the other places where it ought to be.

PHP Filter - a Commonly Used Feature

In spite of this, it's very common for people to use the input filter. Classically, when someone knows some PHP, but is just beginning to learn Drupal, they find some logic they want in their website that they can't work out how to do it. At least, they can't work out the "Drupal way" to do it. So they go for the obvious work-around - put the logic into the Body of whatever page they're creating.

But, eventually, you learn better ways of doing things, and you learn just why the PHP filter is a bad idea, so you want to disable it on your site. Before disabling the "PHP filter" module, you need to make sure that none of your current website content uses it. How do you go about this?

You need to run some database queries to make sure you've caught them all.

Step 1: Find the input formats that use the PHP filter

The PHP Filter is simply one formatter that you can use in an "Input Format" (like "Filtered HTML" and so on). Most people would only enable the PHP Filter in a single text format that they have created especially for this task, maybe named something like "PHP Code". But don't bet on it. Some sites may have enabled the PHP Filter on other Text Formats as well.

SELECT * FROM `filter` WHERE module = 'php' and status = 1

(Note - if you're using a prefix for your tables, you'd obviously need to prefix the table name 'filter'. If you use prefixes, you'll know what I mean, so I'm only going to point this out once in this post.)

This will show you all the input formats that use the PHP filter. In my case, I only had one, and it was Input Format number '2' (look in the 'format' column of what this query spits out.)

Step 2: Find all nodes that use those input formats

We now need to find all nodes that use this input format.

SELECT * FROM `field_data_body` WHERE body_format = 2

or, if you are checking for multiple input formats:

SELECT * FROM `field_data_body` WHERE body_format IN (2, 5)

This will show you all the nodes in your site that use those input formats.

Look at the 'entity_id' column. That will tell you the node ID of each node.

Step 3: Fix those nodes so that they don't use the PHP Filter

Now you need to go to each of those nodes in turn and fix them. They need to be on a different Text Format, one that doesn't use the PHP Filter at all. To load each node, go to yoursite.com/node/nnnn, where nnnn is the node ID you just found in the database.

How to get rid of the PHP from the node will depend on why you originally used the PHP code.

It may be that you aren't even using PHP in some nodes, and you can just change the Text Format to a different one, check it still looks OK, and move on to the next node. Or it may be that your PHP use was so simple you can do without it. Sometimes, you may need a module from Drupal's contrib repository, or even a custom-coded module. That's beyond the scope of this guide.

Step 4: Don't forget blocks

Oh yes.

It's just possible (:cough:) that you might have added a custom block to your site, and put some PHP code in there as well.

SELECT * FROM `block_custom` WHERE format = 2

From the results of that query, you can probably find the block in the Blocks Administration screen of your Drupal site.

But, in case you have a lot of blocks, the 'bid' column gives you the block identifier. You can load this page: yoursite.com/admin/structure/block/manage/block/[bid]/configure, where [bid] is the block identifier you got from your query.

Step 5: Tidy up

That's it. You can now edit the text formats which had the PHP filter in, to either delete them or disable the PHP filter. Then you can disable the PHP Filter module from your site.

Have I missed anything? Are there other common places where PHP code might lurk in the database? Please plug any gaps in the comments section below.

Blog Category: 

Comments

W.M.'s picture
Submitted by W.M. on

As for me, I need it and I use it and I will not get rid of it. Why care about writing modules when I can just do it within a node with PHP :-) ?! No complexity needed. 

karlos's picture
Submitted by karlos on

Security. Performance. Writing a block in code takes maximum of 5 minutes, you have all comfort of IDE ... PHP filter should die years ago!

WorldFallz's picture
Submitted by WorldFallz on

I recently undertook a ginormous d6 -> d7 site migration and as one of the architectural goals I determined to not use any PHP in the UI. Period. I get all the reasons why people do it-- and I've occasionally done it myself over the years. So I left the PHP module disabled-- fully expecting to 'have' to enable it at some point down the road.

Why write block hooks when you can just put a tiny bit (sometimes just 3 lines) of php into the visibility settings textbox?

Why write a views plugin or custom template when when you can just use the php filter and put a tiny piece of php into a global text field or use the views_php module.

Knowing that it was removed from d8 was my impetious. But having done it, I'm ecstatic that I did. Now ALL of my code is in the file system and version controlled. I can even easily reuse the argument handling code in many disparate and unrelated views using hook_views_pre_view. Any time I need to change something I can just use my IDE's search and edit functions. I can set break points. Examine variables. Debug it. It's brilliant.

Did it take a litte extra time to do it that way initially? Sure it did. But now, having it set up, I'm saving way more time than it cost to configure it.

Plus all the often stated security and performance benefits as well.

James Oakley's picture
Submitted by James Oakley on

Thank you.

And you've identified some more places where php code might be lurking - such as block visibility settings, views global text areas, and (one I recently noticed, but not for having used PHP there) panels "new content" blocks.

WorldFallz's picture
Submitted by WorldFallz on

oh yeah-- panels for sure. And don't forget panels visibility rules as well-- I had completely forgotten I put some PHP there too.
And all these disparate locations is also another big drawback-- there's no easy way to find it all. It really is best to not do it at all. Then you don't have to worry about where else you can look when something goes south.

loopduplicate's picture
Submitted by loopduplicate on

The Paranoia module is handy for making sure that no one can use PHP from the UI. "The Paranoia module attempts to identify all the places that a user can evaluate PHP via Drupal's web interface and then block those."

https://www.drupal.org/project/paranoia

Cheers,
loopduplicate

James Oakley's picture
Submitted by James Oakley on

I hadn't met that module before - thanks for the recommendation.

Additional Terms