I am having trouble wrapping my head around the importance of Type hinting in PHP.
Apparently \'type hinting\' in PHP can be defined as follows:
makes you code more stable, especially if the project is large
the code is more readable, cleaner and professional
gives you autocomplete in the IDE
code sniffers like phpstan can found where you are calling a method with wrong param
you can easier understand the code and how methods are working when come to a new project
without type hint if you would call your method with wrong object nothing would happen because $song->title and $song->lyrics would return null, with type hint exception is thrown
Type hinting is a natural process. At first it may seem like extra work but it is very helpful as your project grows in PHP. It allows for better readability and makes error control and strict programming conventions easier to apply.
Initially, you must implement the ‘contract’, where the contract is a php interface which can ‘lock’ constants and the key public methods and their arguments, as such:
interface SongInterface {
//...
}
class Song implements SongInterface
{
public $title;
public $lyrics;
//...
}
Then continue with the actual execution part:
$song = (object) new Song;
$song->title = (string) "Beat it!";
$song->lyrics = (string) "It doesn't matter who's wrong or right... just beat it!";
function sing(SongInterface $song): string
{
$html = (string) "Singing the song called " . $song->title
. "<p>" . $song->lyrics . "</p>";
return htmlentities($html, ENT_QUOTES, 'utf-8');
}
echo sing($song);
Using an interface, you only define the functions and then implement it in a song class. This way you can always inject another song class (with newer functionalities and changes) without breaking your application. Check out oop interfaces: http://php.net/manual/en/language.oop5.interfaces.php
Since php7, you can also define the return type of a function. https://wiki.php.net/rfc/return_types
Is it necessary? No
Is it a best-practice? Yes
Which PHP version supports it? PHP 5.6 for classes only, PHP 7+ allows type-hinting for primitives (int, string, boolean, etc) as well.
How is it useful?
Your code would run fine with or without the type hint.
A type hint simply forces you to pass something of a specific type to that function/method.
E.g.
function displayNames($names)
{
foreach ($names as $n) {
echo $n;
}
}
This function would work fine assuming the user passed in an array as follows.
displayNames(array('Tom', 'John', 'Frank'));
However, PHP would allow the user to pass anything in, such as a string, int, bool, object, etc. None of these would act how you expect when it reaches the foreach
inside of the displayNames
function.
Adding an array
type hint enforces the fact that this function expect $names
to be an array.
function displayNames(array $names)
{
// We now KNOW that $names is an array.
foreach ($names as $n) {
echo $n;
}
}
An array is an easy example, but as you stated you can also type hint objects. In that case it allows the developer to only accept an instance of a Database Connection in a doSqlQuery()
method for example.
You should know
PHP versions below 7 ONLY allow type hints for classes (including interfaces), and arrays. In order to type hint for string
, int
, bool
, etc you need to be using PHP 7.
Type hinting isn't required, but it can allow you to catch certain types of mistakes. For example, you might have a function or method which requires an integer. PHP will happily convert "number looking strings" into integers, and this can cause hard to debug behaviour. If you specify in your code that you specifically need an integer, this can prevent those kinds of bugs in the first place. Many programmers consider protecting their code in this way to be a best practice.
As a concrete example of this in action, let's look at an updated version of your index.php
file:
index.php
<?php
include 'Song.php';
include 'Test.php';
$song_object = new Song;
$test_object = new Test;
$song_object->title = "Beat it!";
$song_object->lyrics = "It doesn't matter who's wrong or right... just beat it!";
$test_object->title = "Test it!";
$test_object->lyrics = "It doesn't matter who's wrong or right... just test it!";
function sing(Song $song)
{
echo "Singing the song called " . $song->title;
echo "<p>" . $song->lyrics . "</p>";
}
sing($song_object);
sing($test_object);
As well as the new Test.php
file I added:
Test.php
<?php
class Test
{
public $title;
public $lyrics;
}
When I run index.php
now, I get the following error:
Output:
Singing the song called Beat it!<p>It doesn't matter who's wrong or right...
just beat it!</p>PHP Catchable fatal error: Argument 1 passed to sing() must
be an instance of Song, instance of Test given, called in test/index.php on
line 22 and defined in test/index.php on line 15
Catchable fatal error: Argument 1 passed to sing() must be an instance of
Song, instance of Test given, called in test/index.php on line 22 and defined
in test/index.php on line 15
This is PHP letting me know that I tried to use the wrong type of class when I called the sing()
function.
This is useful because, even though the above example worked, the Test
class could be different than the Song
class. This could lead to hard to debug errors later on. Using hinting in this way gives developers a way to prevent type errors before they cause issues. This is especially useful in a language like PHP which is often eager to auto-convert between types.
Type hinting is like the name says more of a hint. It allows developers to see what classes may be passed as arguments and prevents them from passing wrong arguments. Thats especially helpful if you're working on the same project with more than just one person and/or the code is meant for open source.
In php7 type hinting for string, int, (mixed) and array have been added so you don't need only classes but also can use the standard php types