PHP7: Type-casting Function Parameters Tip

I am loving PHP 7!

As an lower-division ComSci student, we learned basic programming methods using Pascal.  It was good in that it taught you, among other things, strict typing which we learned to use to our continuing advantage when we later progressed to the C programming language.

I love that PHP7 has strong typing for functions - both in the parameter declarations and in the the return type.  For example:

function foo(array $bar): array

In this declaration, I'm stating that the function, foo() accepts a single input parameter of type array and returns type array. 

Let's enable strict typing and make the function do something... like push a random number onto the array...

<?php
declare (strict_types = 1);

function foo(array $bar): array
{
    array_push($bar, mt_rand(1, 100));
    return($bar);
}

$myArray = array();
echo 'my array has ' . count($myArray) . ' elements' . PHP_EOL;
$myArray = foo($myArray);
var_export($myArray);
echo PHP_EOL;
echo 'my array has ' . count($myArray) . ' elements' . PHP_EOL;

When this code executes, it will generate the following output:

my array has 0 elements
array (
  0 => 82,
)
my array has 1 elements

So far, so good, right?

This only worked because we initialized the $myArray parameter to type array().  In most common cases, you're probably used to initializing your variables, that you're going to use for array storage, to null or the empty string.

If we change the line to:  $myArray = null;  -- this happens:

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to foo() must be of the type array, null given, called in /tmp/array.php on line 12 and defined in /tmp/array.php:4

We can update the code to trap the exception, but it's still going to throw an exception.  

Let's update the code to trap the exception in the invocation:

<?php
declare (strict_types = 1);

function foo(array $bar): array
{
    array_push($bar, mt_rand(1, 100));
    return($bar);
}

$myArray = null;
echo 'my array has ' . count($myArray) . ' elements' . PHP_EOL;
try {
    $myArray = foo($myArray);
} catch (TypeError $e) {
    echo 'CAUGHT EXCEPTION!' . PHP_EOL;
    exit($e->getMessage() . PHP_EOL);
}
var_export($myArray);
echo PHP_EOL;
echo 'my array has ' . count($myArray) . ' elements' . PHP_EOL;

Now when we run the code, we generate this output:

my array has 0 elements
CAUGHT EXCEPTION!
Argument 1 passed to foo() must be of the type array, null given, called in /tmp/array.php on line 13

Better because we're maintaining control over program flow and execution...but I want to be able to pass in a null value...

To be able to do this, and throw an exception and still type-cast the $bar parameter as type array, I simply need to default the value in the declaration to null:

function foo(array $bar = null): array

When I execute the program now, I avoid throwing the exception and I add to the array as evidenced in the output:

my array has 0 elements
array (
  0 => 74,
)
my array has 1 elements

Next, I want to talk about what happens if, because of processing, we can't return an array.  We've declared the function as returning an array but, let's say that processing prevents us from adding to the array if the array is already null:

<?php
declare (strict_types = 1);

function foo(array $bar): array
{
    if (count($bar)) {
        array_push($bar, mt_rand(1, 100));
    }
    return($bar);
}

$myArray = null;
echo 'my array has ' . count($myArray) . ' elements' . PHP_EOL;
try {
    $myArray = foo($myArray);
} catch (TypeError $e) {
    echo 'CAUGHT EXCEPTION!' . PHP_EOL;
    exit($e->getMessage() . PHP_EOL);
}
var_export($myArray);
echo PHP_EOL;
echo 'my array has ' . count($myArray) . ' elements' . PHP_EOL;

When I execute this code, I throw another exception because I didn't push a value onto the array (because I am only pushing values onto non-empty arrays) and so, because the function has been declared as returning an array, and null is returned instead, I get this output:

my array has 0 elements
CAUGHT EXCEPTION!
Return value of foo() must be of the type array, null returned

In order to tell the function that it's ok to return an variable of type array OR type null, I make one minor adjustment to the function declaration header:

function foo(array $bar = null): ?array

Note the placement of the question mark (?) between the colon and the "array" keyword at the end of the function declaration.  Under PHP 7.1, we're telling the interpreter that it's ok to return a function OR a null value to the caller, and I get this output:

my array has 0 elements
NULL
my array has 0 elements

To summarize, we've learned how to enable strict-typing, and how to declare a function parameter type and how to accommodate a default value for the parameter. 

We also learned how to declare the function's return type and how to expand that definition to allow either the return type or a null value to be returned.

In practice, this gives a lot of flexibility to your code in terms of the being able to handle edge cases or null values both the parameters of your functions and their returned types.

And, finally, one last comment - you do not need to enable strict typing for all this work.  Strict typing can be a blessing as well as a curse and until these new features of PHP7 are second nature, you may be better off leaving off the strict typing.

Happy Coding!

 

Full code listing:

<?php
declare (strict_types = 1);

function foo(array $bar = null): ?array
{
    if (count($bar)) {
        array_push($bar, mt_rand(1, 100));
    }
    return($bar);
}

$myArray = null;
echo 'my array has ' . count($myArray) . ' elements' . PHP_EOL;
try {
    $myArray = foo($myArray);
} catch (TypeError $e) {
    echo 'CAUGHT EXCEPTION!' . PHP_EOL;
    exit($e->getMessage() . PHP_EOL);
}
var_export($myArray);
echo PHP_EOL;
echo 'my array has ' . count($myArray) . ' elements' . PHP_EOL;