PHP – Best Methods for Function Parameter Validation

designdesign-patternsfunctionsmethodsPHP

I've been dabbling with the idea of creating my own CMS for the experience and because it would be fun to run my website off my own code base.

One of the decisions I keep coming back to is how best to validate incoming parameters for functions.

This is mostly in reference to simple data types since object validation would be quite a bit more complex.

At first I debated creating a naming convention that would contain information about what the parameters should be, (int, string, bool, etc) then I also figured I could create options to validate against. But then in every function I still need to run some sort of parameter validation that parses the parameter name to determine what the value can be then validate against it, granted this would be handled by passing the list of parameters to function but that still needs to happen and one of my goals is to remove the parameter validation from the function itself so that you can only have the actual function code that accomplishes the intended task without the additional code for validation.

Is there any good way of handling this, or is it so low level that typically parameter validation is just done at the start of the function call anyway, so I should stick with doing that.

Best Answer

The general solutions to this problem are type safety (so that values are valid by construction) and encapsulation (so that values cannot be invalidated after construction). If your inputs and outputs have meaningful types, then the constructors of those types can enforce the properties you want. If validation is centralised, you don’t have to repeat it.

Let’s talk in pseudocode for a moment. As a contrived example, consider a function area(w, h) that computes the area of a rectangle. If you type the function as:

int area(int w, int h)

Then there is no guarantee that any of the invariants hold:

  • w and h are lengths

  • Being lengths, they must be non-negative

  • The result is an area

To enforce input constraints, you can always add validation to the function body:

int area(int w, int h) {
    assert(w >= 0);
    assert(h >= 0);
    return w * h;
}

Not only is this cumbersome, but it remains the responsibility of the caller to validate the result. If we use types that represent our units:

Area area(Length w, Length h) {
    return w * h;
}

Then nobody can give us a Volume when we expected a Length, and since a length cannot be negative, we don’t need to check for that.

PHP doesn’t enforce types statically, but you can prevent the construction of invalid objects by throwing exceptions from constructors that receive invalid inputs, and using immutable objects or accessors to prevent later invalidation.

Related Topic