In the latest versions of PHP, improvements have been introduced regarding type support. Although we are shocked by it being the last day of the 3x1 promotion for CodelyTV Pro, in this video we will see how to take advantage of it. At the end of the post, you have the instructions to enter the raffle for a ticket to Polycon!
Dynamic Types
A language is dynamically typed when it deduces the data type of variables and we do not have to indicate it. In the following example, we see how PHP would deduce the resulting type from adding an int
and a string
that contains an integer:
var_dump(1 + "1"); // Output: int(2)
Being dynamically typed and interpreted, PHP does not have a compilation process; rather, it is at runtime when PHP validates whether a certain variable has a certain method or not. This is known as Duck Typing:
function greeting($from, $to)
{
return $from->name() . " says hello to " . $to->name();
}
echo greeting("Rafa", "Javi"); // Output \*at run-time\*: Fatal error: Uncaught Error: Call to a member function name() on string
final class Person
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function name()
{
return $this->name;
}
}
$rafa = new Person("Rafa");
$javi = new Person("Javi");
echo greeting($rafa, $javi); // Output: Rafa says hello to Javi
That said, let's take a look at the evolution of PHP regarding types:
Type Declaration (previously called Type Hinting)
Starting from PHP 5.0, we have the ability to specify the data type that a certain variable contains when received as an argument. This brings some robustness to our method contracts and leaves behind the possibility of Duck Typing as we saw before: Despite being an advance, it still had its limitations: Only classes or interfaces could be specified, not primitive types of the language.
- PHP 5.1 introduced the ability to specify
array
as input type - PHP 5.4 introduced support for
callable
, allowing us to ensure that we received a first-class function andno value
- PHP 7.0 introduced support for primitives like
bool
,string
,int
, andfloat
- PHP 7.1 introduced support for
iterable
, understanding that it accepts bothTraversable
implementations and primitivearrays
So, we can refactor the previous function to something like:
function greeting(Person $from, Person $to)
{
return $from->name() . " says hello to " . $to->name();
}
echo greeting("Rafa", "Javi"); // Output \*at run-time\*: Fatal error: Uncaught TypeError: Argument 1 passed to greeting() must be an instance of Person, string given
$rafa = new Person("Rafa");
$javi = new Person("Javi");
echo greeting($rafa, $javi); // Output: Rafa says hello to Javi
Return Type
PHP 7.0 introduces the ability to add return types in our functions, finally giving them the robustness they deserve. Now we can declare interfaces that explicitly express all the necessary information for implementations, and the clients of these interfaces will have all the necessary information:
function greeting(Person $from, Person $to): string
{
return $from->name() . " says hello to " . $to->name();
}
Furthermore, PHP 7.1 introduces the option to specify void
as a return type. This way, we can explicitly indicate that a certain function does not return any value and, therefore, that function aims to produce a side-effect like the examples we discussed in the video. Even today, we must indicate the exceptions that can be thrown by a method through documentation, while in other languages, they can be specified as part of the contract as well (Java annotations).
Strict Types
Another functionality regarding types incorporated in PHP 7.0 is the declare(strict_types=1);
statement. This statement prevents automatic casting that PHP performs if this statement is not specified:
<?php
function greeting(string $fromName, string $toName): string
{
return $fromName . " says hello to " . $toName;
}
echo greeting("Rafa", 123); // Output: Rafa says hello to 123
As we see below, if we specify this statement, even though there is a casting available from int(123)
to string("123")
, PHP does not perform it and throws a Fatal error:
<?php
declare(strict_types=1);
function greeting(string $fromName, string $toName): string
{
return $fromName . " says hello to " . $toName;
}
echo greeting("Rafa", 123); // Output: Fatal error: Uncaught TypeError: Argument 2 passed to greeting() must be of the type string, integer given
Ideally, strict type declaration would have been able to declare it at the project level. However, since defining something like this in php.ini
would affect the code of our dependencies, they preferred to be conservative and define it at the project level. Despite this, considering the maturity of Composer in the PHP ecosystem, it might have been beneficial to declare it within composer.json
, or to keep it separate in a specific file like strict_types.json
, which would allow setting exclusion rules based on directories. In any case, this is not the case. Hence, we recommend that you modify the “New PHP Class” template of your IntelliJ/PhpStorm to include this declaration by default.
Nullable Type
PHP 7.1 introduces the ability to explicitly specify that a certain type can be null
. This works very well for the practical cases we discussed in the video, but following the example of the post, it would allow things like:
<?php
declare(strict_types=1);
function greeting(string $fromName, ?string $toName): ?string
{
if (is_null($toName)) {
return null;
}
return $fromName . " says hello to " . $toName;
}
echo greeting("Rafa", "Javi"); // Output: Rafa says hello to Javi
echo greeting("Rafa", null); // Output: "" (empty)
echo greeting(null, "Javi"); // Output: Fatal error: Uncaught TypeError: Argument 1 passed to greeting() must be of the type string, null given
Conclusion on Types and PHP
As we have seen, the evolution of type support in PHP from version 5 to 7.1 has been remarkable. Although this does not represent any improvement over the functionalities available in other languages, it at least updates and modernizes the language to allow a programming style with which, at least we, feel much more comfortable 🙂 Lastly, I remind you that today is the last day to take advantage of the 3x1 offer for Codely TV Pro. The course platform of CodelyTV 🤓
Raffle for Polycon 2017 Ticket 🎟️🎯🐘
On October 6th and 7th, the Polycon Software Engineering Conference will take place in Barcelona. This is a language-agnostic conference being held for the first time this year and already features top international speakers. Topics will range from Hexagonal Architecture to Event Sourcing, passing through Microservices, news from Symfony 4, graph databases like Neo4j, and much more. For more information, you can visit the official Polycon website. They are really good people and they have generously given us a ticket to raffle among CodelyTV followers, so you just need to follow 3 simple steps to enter the raffle:
- Follow @polycon_io
- Follow @CodelyTV
- Retweet this tweet
With this, you will enter the raffle for a ticket valued at €84, and on Tuesday, September 19th, we will announce the winner. Good luck! 🙂