I've built up a collection of string functions that do various things and I've noticed that I don't actually have any internal function checks that make sure the variable is a string before something is done with it.
So on a few occasions during development I've accidentally passed something other than a string resulting in an error.
Now, I'm wondering if this is this something I should be doing all the time. First checking to make sure the correct type of data has been sent/check for things that could potentially go wrong first, log them in some way, then if all is okay, do something with it.
Is this something I should be sticking to?
Description ¶ Returns the type of the PHP variable value . For type checking, use is_* functions.
The default arguments must be constant expressions. They cannot be variables or function calls. PHP allows you to use a scalar value, an array, and null as the default arguments.
PHP supports first-class functions, meaning that a function can be assigned to a variable. Both user-defined and built-in functions can be referenced by a variable and invoked dynamically.
Passing Arguments There are two ways to pass arguments to a function: by reference or by value. Modifying an argument that's passed by reference is reflected globally, but modifying an argument that's passed by value is reflected only inside the function.
You can see this is a somewhat debatable topic. This is my take:
Type Hinting
Use type hinting when possible. Type hints are not possible in PHP for primitive types, so yes, you should check to ensure you've received valid arguments. If you have not, your function can throw an Exception or return some default value like null or false.
Defensive Programming
The idea of writing testable code is that failures are not silent or mysterious. There's no reason to avoid explicit argument validation: be verbose and your code is more clear and usable.
On top of validating your arguments, you can implement an error handler to catch the edge cases. But you should be validating most arguments, especially if they have an effect on persistent data (like your database).
Murphy's Law is in full effect, therefore you must contend with as many predictable bugs as you can. An invalid argument is an easily predictable bug -- failure to validate it is a timebomb in your code. Calling is_string
, for example, is easy and diffuses the bomb.
Boxing
Another consideration is to "box" your variables. This leads to very verbose code, but it does have the advantage of allowing type hints for primitives.
I've never seen anyone actually do this though their entire codebase, but it is out there. There are SPL classes available for primative types, so you'd wind up like this:
function stringThing (\SplString $myString) { ... }
stringThing(new \SplString('This is my string'));
SplTypes enforce the primitive type and throw exceptions when it is misused. From the documentation:
$string = new SplString("Testing");
try {
$string = array(); // <----------this will throw an exception
} catch (UnexpectedValueException $uve) {
echo $uve->getMessage() . PHP_EOL;
}
SplTypes is a PECL extension, and not always a part of a standard PHP install, so check your extensions before using it. The extension is also considered experimental, though it has been in around for some time now.
You can also create your own box fairly simply:
class myStringBox {
private $string = '';
public function __construct($string=null) {
if ($string)
$this->set($string);
}
public function set($val) {
if (!is_string($string)) throw new \InvalidArgumentException();
$this->string= $val;
}
public function __toString() {
return $this->string;
}
public function trim() { return trim($this->string); } // extend with functions?
}
... but this has a major functional difference in that you cannot directly set a new string value like this:
$stringBox = new myStringBox('hello world! ');
echo $stringBox; // "hello world![space]"
echo $stringBox->trim(); // "hello world!"
$stringBox = 'A new string';
echo $stringBox->trim(); // Error: Call to a member function trim() on a non-object
Instead, you have to use a setter method:
$stringBox = new myStringBox('hello world! ');
echo $stringBox; // "hello world![space]"
echo $stringBox->trim(); // "hello world!"
$stringBox->set('A new world');
echo $stringBox->trim(); // "A new world"
This all leads us back to type hinting, which is probably the most efficient way to NOT have to validate your arguments.
Related Reading
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With