In a framework I am building, I am moving towards making my code more testable as I was previously addicted to the MVC+Singleton pattern and had static classes galore. Since then, I have started to understand more about Unit Testing and TDD so it prompted me to re-factor a lot of code. Part of this re-factoring has driven me to try and use the Extension classes within PHP properly, i.e. not just throw the Exception class but more relevant exceptions.
I have the following class:
<?php
namespace Framework;
class Uri {
public static function new_from_http() {
$uri = '';
if (isset($_SERVER['REQUEST_URI'])) {
$uri = $_SERVER['REQUEST_URI'];
} elseif (isset($_SERVER['PATH_INFO'])) {
$uri = $_SERVER['PATH_INFO'];
}
return static::new_from_string($uri);
}
public static function new_from_string($string) {
return new static(explode('/', $string));
}
protected $uri = [];
public function __construct(array $uri) {
$this->uri = array_values(array_filter($uri));
}
public function get_segment($offset, $default = null) {
if (!is_int($offset)) {
throw new \InvalidArgumentException(
sprintf('%s requires argument 1 to be an integer, %s given.',
__METHOD__,
gettype()
)
);
}
return isset($this->uri[$offset - 1])
? $this->uri[$offset - 1]
: $default;
}
}
Thats all well and good and as you can see, the get_segment method requires an integer otherwise it throws an InvalidArgumentException. The trouble is, I want to create a few more methods which also require integers as an argument and I do not want to cut and paste that code everywhere. What are the best options of consolidating all of these types of argument check so that I can use them within different classes and methods while keeping the messages consistent with one another.
One of my ideas was to extend the exception classes under the framework namespace and have the constructor take different parameters such as:
namespace Framework;
class InvalidArgumentException extends \InvalidArgumentException {
public function __construct($method, $argument, $value) {
parent::__construct(
sprintf('%s requires argument 1 to be an integer, %s given.',
$method,
gettype($value)
)
);
}
}
Which would be called like:
if (!is_int($arg)) {
throw new \Framework\InvalidArgumentException(__METHOD__, 1, $arg);
}
It could also be improved that the \Framework\InvalidArgumentException can get the __METHOD__ value via a back trace.
What other options do I have and what is the best one?
I would extend the /InvalidArgumentException into a NonIntegerException doing basically the same thing otherwise. This way if you wanted to require strings, arrays or any other type, you are able to create new exceptions and you don't have to have crazy logic for determining which message to use.
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