Coming from C# I'm used to overloading my methods with variably typed parameters. Since you can't do this in PHP, I often create methods such as the example below which accept a variable, then I check the type and act accordingly:
showLength('one');
showLength(array(
'one',
'two',
'three'
));
function showLength($stringOrArray) {
$arr = array();
if(is_array($stringOrArray)) {
$arr = $stringOrArray;
} else if(is_string($stringOrArray)) {
$arr[] = $stringOrArray;
} else {
//exception
}
foreach ($arr as $str) {
echo strlen($str).'<br/>';
}
}
output:
3
3
3
5
4
This gives me the same functionality as in C# but it seems a bit messy, as if there is a better way.
Is this the accepted way to do method overloading in PHP (5.3) or is there a better way?
I know a lot of frameworks do this for certain functions where it makes sense, as do some of PHP's core functions. The difference between 'good' uses and 'poor' uses to me is the documentation (docblock). The documentation needs to indicate that the param is of type mixed and the different acceptable variable types.
For example:
<?php
/**
* Function used to assign roles to a user
* @param int $user_id The user's id
* @param mixed $role Either a string name of the role
* or an array with string values
*
* @return bool on success/failure
*/
function addRole($user_id, $role) {
if (!is_array($role)) {
$role = array($role);
}
foreach($role as item) {
Model::addRole($item);
}
return true;
}
I don't like to beat a dead horse, but still, I'll weigh in here.
I wouldn't consider it an anti-pattern; as @Merijn points out, many native PHP functions accept mixed type parameters. Furthermore, many circumstances as your own, require that for succinctness the function accept an element, or a collection, of a given type instead of splitting it over two functions.
Casting to (array)
is a quick and easy way to achieve this functionality:
function printStuff($stuff)
{
foreach((array) $stuff as $key => $value) {
echo sprintf('%d : %s', $key, $value) . PHP_EOL;
}
}
printStuff("foo");
// 0 : foo
printStuff(array("foo", "bar", "qux"));
// 0 : foo
// 1 : bar
// 2 : qux
Using $foo = (array) $foo;
is better1 than $foo = array($foo);
as when $foo
is already an array, it won't wrap it again.
Reference
1 Produces the desired results with scalars; objects produce different results. Objects cast to array will enumerate the properties, so use discretion.
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