[Updated]: Made some changes to the code. Thank you
ithilion and
LoneCatEveryone already knows that in PHP 5 you can specify their type in function arguments, with the exception of ... scalar types, ie: integer, string, boolean, float, etc.
However, on
the type control
manual page , in the comments, Daniel L. Wood provides a rather interesting solution to this problem with the help of an error handler class. The only significant disadvantage of this solution is its performance.
')
Below I will try to tell you how to optimize this solution, as well as whether to use it, in principle, in production releases.
So, let's analyze what the above solution is sinning:
- Absolutely unnecessary debug_backtrace calls. In principle, to solve the problem, just parse the error message. An explicit argument checker smacks of paranoia. Indeed, if we caught a message of the form “Argument N passed to Class :: function () must be an instance of string, string given, ...” - this already gives us every reason to make the right choice. Please note ... string, string ... In case of an error it will be, for example, ... integer, string ... This is enough to determine whether this message is an error or not.
- It has a typo in the type array. 're srou ce' => 'is_resource'.
- Somewhat non-optimal code in some places.
We will try to solve all these problems by rewriting the class as follows:
<? php
class Typehint {
private static $ _types = array (
'boolean,' => 'boolean',
'bool,' => 'boolean',
'integer,' => 'integer',
'int,' => 'integer',
'float,' => 'float',
'double,' => 'float',
'real,' => 'float',
'string,' => 'string',
'resource,' => 'resource'
);
private function __construct () {}
public static function init () {
set_error_handler ('Typehint :: handle');
return true;
}
public static function handle ($ lvl, $ msg) {
if ($ lvl == E_RECOVERABLE_ERROR && strstr ($ msg, 'must be an instance of')! == false) {
$ errmsg = explode ('', $ msg, 13);
return isset (self :: $ _ types [$ errmsg [10]]) && self :: $ _ types [$ errmsg [10]] == $ errmsg [11];
}
return false;
}
}
?>
Let's now take tests and see what we got.
<? php
require_once 'Typehint.php';
Typehint :: init ();
function teststring (string $ string) {return $ string; }
function test ($ var) {return $ var; }
function micro_time () {
$ timearray = explode ("", microtime ());
return ($ timearray [1] + $ timearray [0]);
}
$ start = micro_time ();
for ($ i = 0; $ i <10000; $ i ++) {
teststring ('123');
}
$ end = micro_time ();
echo 'With Typehint:'. ($ end- $ start). 'sec.';
echo "<br /> \ n";
$ start = micro_time ();
for ($ i = 0; $ i <10000; $ i ++) {
test ('123');
}
$ end = micro_time ();
echo 'Without Typehint:'. ($ end- $ start). 'sec.';
?>
Here's what I got:
With Typehint: 0.0787329673767 sec.
Without Typehint: 0.00326299667358 sec.
I note that for the original solution from Daniel, my result was as follows: 0.215523958206 seconds. Those. we won almost 2.7 times the performance.
Nevertheless, as we can see, without the use of a Typehint solution, we would have won more than 24 times the performance. Rather, using it, we lose 24 times.
This suggests an idea of the expediency of its use. See 10,000 calls add to the time of the script almost 0.1 seconds. There is something to think about.
On the other hand, the use of Typehint increases the self-documenting of the code and allows, in some cases, when it is especially necessary, to control the type of arguments passed.
However, it should be noted that ubiquitous strong typing in PHP, in fact, will give you no advantages, since There is no overload mechanism in the language; if the type is declared, problems will arise with the default values of the arguments. In addition, no one can guarantee the return values in language constructs either.
Therefore, it is worth thinking a few times before using this solution or not.
If you still see the expediency and want to use it in your project, I suggest you consider the possibility / necessity of creating some automatic builder who will release the final code for production use by cleaning scalar types in the definitions of functions and methods of classes.
This will be, in principle, easy, at least using the same PHP or Shell.
Good luck in development!
PS Cross-post from my blog:
mikhailstadnik.com/php5-types-control