More Tips for Defensive Programming in PHP

By Jeff Smith

The general definition of defensive programming (as seen in Part 1, an overview piece on Defensive Programming in PHP) being used here is thus:

Defensive programming, simply put, is programming with the intent to anticipate likely failure points. The goal is to circumvent those likely problems before they occur.

This definition is a wide one. Many people argue against defensive programming, but this is often because of the types of methods they have seen espoused by some as defensive programming. Defensive programming should not be viewed as a way to avoid test driven development or as a way to simply compensate for failures and move on.

“Fail Fast” should not be seen as a counter to defensive programming. It all falls under the same umbrella. What are these methods, if not ways to anticipate that your program may fail, and either prevent those, or else ways in which to handle those failures appropriately?

Shield target being hit by arrows

Fail Fast, and Loudly

Simply put, failing fast and loudly means that when an error occurs, it will do so as early as possible, and alert whomever it should alert, as opposed to silently continuing on in an error state that may cause more issues. Here is an excellent article on fail-fast style development. The premise of fail-fast methodology is to fail when acquiring input that might later compromise the program (or, more generally, to enter a failure state as soon as any problems could possibly be detected, rather than allowing bad data to travel and a program to run un-checked, or worse, bad data to be stored somewhere). This is most useful when dealing with user input, or dealing with input that is arriving from outside the script, module, or even out of your system via an API. An example of where this could be employed would be a check for invalid values or data types passed into functions.

function thisTestFunction($testInt)
		// Do something here

One mistake that some programmers make with fail-fast methodology is to simply throw Exceptions and errors out to the user without making proper provisions for handling them. You don’t want normal users to be worried or confused by your error messaging. And more importantly, you don’t want users with malicious intent learning things from the information displayed to them. Display a helpful message to the user, log your errors, and perform any other tasks that need to be a result of that exception. You don’t want to just fail fast, you also want to be loud (know there’s a problem, right away) and secure (don’t let your poor exception handling or complete lack thereof cause even more security issues).

Input Validation

There are many methods by which to validate user input safely.

Typecasting is an interesting way to “validate” user input. Sometimes it goes a bit like this:

$member->property = (int) $_GET['property'];

Instead of using another method to avoid cross-site scripting attacks, the value is simply being captured, typecast, and assigned. This only works when you have an expected type, and any value of that type is safe (Otherwise, you’d need to also check for appropriate int values). The problem with this approach, that I see (in most situations) is that you aren’t really checking the input, you’re just forcing it to become what it should be. This could have unforeseen consequences. Instead, a better approach might be to check for appropriate values using filter_input(). Here is a great article on that subject. Basically, that comes out like this:

$member->property = filter_input(INPUT_GET, 'property', FILTER_VALIDATE_INT);

if (false === $member->property) {
  throw new Exception('Property was not an int');

There are many benefits to using the native filter_input function in modern PHP, and you can read more about them in the aforementioned article or on

Preventing Accidental Assignment in Comparisons

This is an easy, and often noted, tenet of defensive programming. A simple change in the way that you do your comparisons can have great effects. Consider the following:

if($member->property == 12345){
	// Do crazy cool stuff
} else {
	// Don't do any fun stuff

This is a relatively normal comparison, yes? However, what happens if you accidentally use the “=” instead of “==” (or, in most cases, the even better “===”)? A simple slip of the finger on the keyboard? Absentmindedness, maybe? All of a sudden, your comparison now reads true, all of the time, in all cases. Unless you have a good IDE warning you about this, how long will it take you to find out? In some cases, this could be a silent error for some time. However, there’s an extremely simple way to prevent this:

if(12345 == $member->property){
	// Do crazy cool stuff
} else {
	// Don't do any fun stuff

Now, if you accidentally use one equals sign, the error will not be silent. Obviously, this may not occur often, it may be mitigated by your testing, and it’s not useful in all cases, especially when doing variable to variable comparisons. But it’s still not a bad idea if this tends to happen to you.

Dealing with Try/Catch and Exceptions

try/catch statements are another hot topic among PHP developers. Let’s first get a quick look at what we’re talking about.

try {
	if($member->property <= 0){
		throw new Exception("Value must be 1 or greater");
	// If no exception was thrown, this will be output.
	echo "The value is acceptable";
} catch(Exception $e) {
	echo 'Message: '.$e->getMessage();

A well known tool of defensive programming is the try/catch statement and the Exception class. These are excellent for catching and logging errors, when used correctly. A good programmer will employ try/catch statements to anticipate possible errors or other situations that might disrupt the normal flow. When those Exceptions occur, they must be handled in an appropriate way. The user of the application, where required, should get a reasonable error message that is as useful as it can be without divulging sensitive information. The administrator(s) of the application should receive detailed alerts and/or logs. Exceptions that are mishandled, or ignored, ignore the “Fail Loudly” advice, and may allow the program to continue in essentially a silent error state for some time, which is not good for anyone involved.

For a bit more on exceptions in PHP, see here and here.


Transactions are a feature of databases that allow queries to be grouped together, so that if one query fails, all of them fail. This is an implementation of ACID, about which you can read more here. The idea is that grouping multiple queries together into one process can sometimes be a safer and more stable solution, especially when the queries depend on each other. PHP developers often completely ignore transactions, or assume that they are unnecessary, but when interacting with databases, a little bit of defensive programming can go a long way. Transactions are discussed in more depth in this excellent post, but in a nutshell, transactions allow you to run your MySQL updates, and then check the results before actually committing the results. If you are using PDO (you should be), you may use PDO methods to begin a transaction, commit the results, as well as roll back. In addition to the aforementioned overview of transactions, delve into them further with this in-depth guide.

Here’s a quick example of what the use of transactions in PDO might look like:

	// Start the transaction

	// Perform one update
	$statement1 = $db->prepare("QUERY LANGAUGE HERE");

	// Perform another update
	$statement2 = $db->prepare("MORE QUERY LANGUAGE HERE");

	// Commit the transaction
} catch(PDOException $ex) {
	// If an exception occurs, first, roll back updates
	// Then, in this block, further handle the exception


Again, these are just general tips. Obviously, each of them has their uses and each has notable situations where it would not be used. However, if you take concepts like these and work them into your daily development regimes, it can make you more efficient at what you do. And while this is generally a topic that is more applicable to developers who are currently learning PHP, it’s a good refresher on practices for everyone.

If only a single thing is taken away from this, especially by newer developers, it is that you should program defensively – plan for the possibility of mistakes and errors. Handle them appropriately. Don’t allow silent errors to progress. Fail fast. Test your code. By building robust applications that test for and resolve issues, and anticipate and handle future ones, you are making your applications more dependable, and hopefully assisting in the creation of a better user experience from behind the scenes.

  • md2perpe

    Shouldn’t it be $db->commit(); i.e. with parenthesis?

    • Jeff Smith

      Definitely so! Good catch.

    • Bruno Skvorc

      Sorry and thanks, fixed!

  • Marcin Hubert

    if(12345 == $member->property){

    this is yoda condition, and it’s anti-pattern! You should avoid writing code like that, because it’s harder to understand…

    • Jeff Smith

      Thanks for your feedback!

      My personal opinion is that it’s not harder to understand at all, especially if you’re consistent with it. Several larger codebases have implemented similar rules (Symphony, WordPress), indicating that I’m not the only one who thinks that!

      However, if you’re not on a project that has a rule one way or the other, you’re obviously free to do whichever suits you and your team the best, and whichever you feel will be better for the project and perhaps the maintainers that follow after you!

      • Diamenta Princessa

        I know people are doing yoda, but I’m not a fan also. Good IDE is everything you need.

        • Jeff Smith

          Yeah, I definitely see that there are two sides to that coin, but to me it’s a harmless and easy to implement suggestion for people. Really I suspect it’ll matter what project you’re working on. One thing you wouldn’t want to do is switch patterns (for anything really) partway into a project… make it consistent. Inconsistency is just as likely to run you up against problems as anything else!

          • Diamenta Princessa

            So about consistency you mentioned, I’m doing actually opposite in my current work. While refactoring legacy code, I’m using also PSR recomendations (and yoda style is described there as non human friendly, heh, I agree as a human :D). I saw few styles in the codebase I’m working with already, but it doesn’t mean you should keep the style which is represented in the current file ;). If you see the legacy part of code, change even the one line, not entirely file. But refactor it. And this is the long-term transition process, but this is the only way to switch “old school” style to standards. Probably that’s the thing you can discuss with your team, I agree. So, in my team, yoda is not your friend ;). The same for itinerary conditions, they can be very useful, but for better readability is a lot better to avoid them and use only for simple conditions like returning true / false or 0 / 1.

          • Jeff Smith

            Definitely, switching techniques to fit you, your team, or modern coding standards is great. I guess I didn’t explain what I meant very well there – re: inconsistent coding. If the code base uses (whatever pattern/standard/etc “foo”), and you use (new pattern/standard/etc “bar”), and you leave all the “foo” in place, then later maintainers will have more trouble with the inconsistency than if you’d just left it. If you’re refactoring the legacy code to match the newer stuff… that’s totally different!

            One thing that you touched on that frustrates me is developers who choose not to refactor bad/old code when encountered. There’s a huge set of circumstances where you cannot, right – time constraints, employer/team making time decisions for you. But when it’s just the programmer, on their own projects, it’s nice to see people making small efforts to make the Internet a little better, and easier for each other to maintain :D

          • Diamenta Princessa

            Yeah, it’s true. There is one great rule I’m always following. If you will postpone to refactor the legacy bad code, it will be always bad. I remember the guy who was saying that there is no reason to refactor some class as it’s used still in few places, but already deprecated. But the fact was that it was used as the deprecated class for few years already. And it will be used for another few years for sure. So there is always a compromise: you have no time to change the whole functionality at once, but when refactoring step by step, you can finally change the whole functionality as it will be testable, more understandable and more common to you and your team.

    • Przemysław Lib

      It would be if You could prove that time spend on getting comfortable with yoda notation is BIGGER then time spent on bug hunting that missing ‘=’ character.

      That is silly assumption/hypothesis. Do not know any dev who never spent a half a day on finding that single missing ‘=’. Multply it by ‘few times’ it will happen to anybody in the profession, and then suddenly it’s hard to justify not spending couple of hours on getting used to yoda notation.

      Or maybe I’m wrong, but hey! Fill free to post results of some study.

  • Diamenta Princessa

    Nice article, it would be good to mention about usage of Value Objects. I think it’s a good idea to parse values through Value Objects and throwing InvalidArgumentException, or other custom exceptions if fails.

    • Jeff Smith

      It seems like the amount of topics one could cover under this umbrella are endless, doesn’t it? I suppose that’s better than having to struggle for things to say, though… and you never know, maybe someday a part 3 could be put together :)

      Thanks very much for the suggestion!

      • Diamenta Princessa

        Definitely, I’m waiting for the next one then :).

  • Tomasz Rutkowski

    “beginTransaction()” should be before try.
    In that moment when you start transaction and some error occur.
    You generate new error by rollBack not started transaction.



Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in PHP, once a week, for free.