As any PHP developer knows, PHP handles missing arguments in its own idiosyncratic way. That is, if you call a function or method and don’t include all of the required arguments, PHP emits a warning but continues to execute.
Best practice for dealing with this is to ensure that all of your custom functions and methods include guard clauses for checking for the presence of arguments; you could also go further and check the type of those arguments as well. For example:
However, sometimes this isn’t a viable strategy. In my daily work I am dealing with a large application that has more than one hundred controller classes and more than a thousand methods - most of which were implemented without guard clauses (usually by me before I knew any better!).
Our application uses CakePHP 2, which has automagic routing, e.g.
/posts/view/2 will automatically map to
PostsController::view(2). Sometimes users type in URLs manually and may miss parameters out by accident. Taking the
above example, this can cause messy error log entries:
With this code, in the event of a user visiting
/posts/view/ without passing in the ID, you will get a warning from
PHP for the missing argument, a notice for using an undefined variable and probably some other errors in your view file
when you try to use the ‘$post’ variable.
I suppose there is also the potential for destructive behaviour if your method is going on to
DELETE in your database and the code isn’t checking for required parameters first…
Rather than go through hundreds of methods to add guard clauses, I came up with a simpler solution. Our application uses a custom error handler class. I added the following new method to that class:
This method is very simple - it checks the error description from PHP to see if it matches the pattern of the warning
message emitted by a call to a function or method with a missing argument, and returns
false as appropriate.
The error handler has another method called
handleError which is called by Cake and which receives a number of parameters,
one of which is
$description. So, I updated that method to call this new method and throw a custom Exception class:
The result of this is that any instances of methods or functions being called with missing parameters show up in the error log as just one entry, and the script stops executing any further, preventing any destructive behaviour which could occur.
I hope someone else finds this useful!