My friends and family are under attack in Ukraine.
Donate to protect them directly or help international organizations.

Common PHP Mistakes

July 19th, 2014

I was recently asked by one of my readers to give feedback on the following article he read: 10 Most Common PHP Mistakes. It is well written and very thorough. Most of the tips are specific to PHP, others are about web programming in general or database performance. It's a very good read. I was also asked to contribute to this list, so here are 7 more tips. I found these very common in my code reviews or various audits.

11. Forgetting to cache

Websites can be slow due to a variety of reasons. Adding a cache layer not only improves the user's experience, but also tremendously reduces the load on your servers. There are many ways to cache and you can combine different cache types: query cache, Redis, Varnish, etc.

12. Allowing SQL injection

Security is easy to overlook, especially when starting out. SQL injections are extremely dangerous. Let's say you write this in your code:

"SELECT first_name FROM users WHERE id = " .$input['user_id'] . ";"

It is possible for the user to provide a malicious input, such as:

13; DELETE FROM users WHERE 1

Once your query is concatenated, it will end up looking like this:

SELECT first_name FROM users WHERE id = 13; DELETE FROM users WHERE 1;

You can protect yourself by filtering the input, such as making sure that it's a number. Another good practice is to always use prepared statement when using PHP variables in SQL. Example:

$stmt = $pdo->prepare("SELECT first_name FROM users WHERE id = :user_id");
$stmt->bindParam(':user_id', $input['user_id']);

This will make sure that a user simply cannot "break" out of the query. More on prepared statements.

13. Disabling error reporting

When I first started writing PHP in 2003, I was annoyed when my PHP errors or notices showed up on the web. I simply disabled error reporting in production, while keeping them on my local machine to help debug my code. This was a mistake. If any error should happen in production, the user won't see it, but I won't know that something is broken either. For this purpose, you should keep the error reporting. Don't show it to the user but log it to a file, which you can then view. This can be done easily via the php.ini file:

display_errors: off
log_errors: on
error_log: logs/errors.log

14. Staying on the same page after the form was processed

If the form contains errors, you will probably display the same page again and highlight the errors. That's good. But then if the form was successful and processed, such as creating a database record or charging a credit card, you need to redirect the user. Think of it as adding sugar to your coffee. Each time you refresh the page (your user can choose to accept the resubmit warning), another spoon of sugar is added. Do it enough times and you'll have sugar with a hint of coffee, or charge the credit card 10 times. Redirecting the user lets you prevent "replaying" the action. Redirect like this:

header("Location: http://example.com/user/add/success");

15. Reinventing the wheel

The PHP community is incredibly active. There are countless packages that you can install using Composer. Tools include e-mailing, file system, templating, caching, parsing various formats, handling multilingualism, unit testing, etc.

Many people don't realize how many functions come out of the box with PHP. There are thousands of functions that can replace hundreds (or more) of lines in your code, so dig around.

There are also many frameworks that help you organize your code and take a lot of the repetitive, tedious work off your hands. Find a top X list, read some reviews on each and take a pick.

16. Letting your scripts run forever

Don't assume that your script will always finish quickly. Perhaps your script talks to a server that is taking long to respond. Perhaps the user decided to upload a very big file. Perhaps you have a database congestion and your script is just waiting on its turn. Expect the unexpected and use set_time_limit().

Extra trick: determine which scripts should be lighting quick, such as upvoting a comment, and which should be allowed to run longer, such as image processing. Set a time limit based on expected maximum. If there is an unexpected delay, your script will fail (and log an error). Your server won't be overwhelmed, your user won't wait for no good reason (a negative answer is better than no answer at all) and you will also have a log to tell you that something needs fixing.

It's still a good idea to write safeguard in your code, such as checking upload size or setting timeouts on API requests.

17. Ignoring accessibility

What is it? Accessibility is basically making sure that everyone can use your site despite any limitations. To list but a few: can't distinguish some colors, can't see small font, can't see, no fingers, arthritis, multiple sclerosis (even I will forget what was the first menu item if you have 25 of them), etc. I personally know people from each category. Accessibility also applies to the range of devices. Basically, embrace the diversity and design for inclusion.

I recommend a reporting tool such as Wave. Give it a spin. It makes accessibility easy and fun.

Add more tips in the comments! In case you wonder about the image, it's a pressure barrel (beer).

Previous: What is technical debt Next: On ethics and optimism