Why is type hinting necessary in PHP?
Asked Answered
C

7

38

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:

"Type hinting" forces you to only pass objects of a particular type. This prevents you from passing incompatible values, and creates a standard if you're working with a team etc.

So type hinting at the most basic level, is not required to actually make the code work?

I have the following code to try and understand what is going on...

Index.php

<?php
include 'Song.php';

$song_object = new Song;

$song_object->title = "Beat it!";
$song_object->lyrics = "It doesn't matter who's wrong or right... just beat it!";


function sing(Song $song)
{
    echo "Singing the song called " . $song->title;
    echo "<p>" . $song->lyrics . "</p>";
}

sing($song_object);

Song.php

<?php

class Song
{
    public $title;
    public $lyrics;
}

the code does its thing with or without the little type hint in the function sing();

enter image description here

So, this leads me to believe that type hinting is simply a coding convention to make sure only certain classes are used and are not needed to produce functional code, is this correct?

Type hinting, as the quote above suggests, is there to create a standard if you're working with a team.

Am I missing something here?

Cahan answered 11/7, 2016 at 14:4 Comment(7)
Wow, and here I am trying to make it more complicated then it is. Thanks!Cahan
Type hinting helps you catch errors quickly by complaining when you pass it a parameter it can't accept instead of having it accept it and then throw mysterious errors when it's trying to use it as an object of type X while in reality it's an object of type Y.Preen
Ahem, Dependency Injection, too. As it is, you don't have to instantiate a class inside the method.Tonne
See also: #537014Ozone
Type hints and return types, could help intelligent editors.Ozone
See this: radify.io/blog/type-hinting-in-php-good-or-bad-practiceTeaching
There is actually a distinct reason for this in your example, just not the one you're looking for. In the context of your image "Song $song" actually means "A Song object called $song. So, it will always work if you pass in an object of class Song. It will throw an error if any other value type or object of a different class is given. Im surprised no one commented before me...Lox
H
42

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.

Heliozoan answered 11/7, 2016 at 14:12 Comment(4)
This is a very bad example, as the two classes are compatible and therefore there is no issue with using Test in place of Song. In this case, type hinting is actually a handicap which makes the code break, whereas without it the code would just work. Your point (which is valid) would be better made with an example where the protection is needed. As it stands, this feels like it is demonstrating one of the drawbacks of type hinting.Eldrida
@Eldrida quite the contrary, this is a great example specifically because the example currently works. The sing() function is intended to work with a Song, not anything else that happens to share functionality with it. It would be perfectly reasonable to change the Test class at some point since it's just a test, but suddenly the code would break in a completely different place (the sing() function). Type hinting prevents that by throwing the error right where the actual mistake is happening: Something wrong is passed to sing() and only works by coincidence.Rani
That being said, it's also a good example of why type hinting should use interfaces whenever it's possible that different implementations of compatible behaviour exist. Here, both Song and Test fulfill the requirements sing() needs, so the optimal way to code this example would be a type hint against a Singable interface, which can then be implemented by both Song and Test. If Test is later changed and is no longer compatible, the change will break the interface requirements. This of course requires changing the variable access to getter methods.Rani
What you say is true, but your answer doesn't show type hinting preventing a problem - only causing one! In the example you gave, the working code is the one without type hinting; the code breaks when type hinting is added. The hypothetical future scenario it may help with is not demonstrated by your answer. Given the statement "If you specify in your code that you specifically need an integer, this can prevent those kinds of bugs in the first place" it would be better if your answer demonstrated this point, as currently it does not.Eldrida
S
10

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

Seaborne answered 11/7, 2016 at 14:32 Comment(0)
H
6

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.

Hornbill answered 11/7, 2016 at 14:15 Comment(0)
L
4

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?

  1. Getting hints by the IDE (depends on the IDE).
  2. Standardizing coding style in team projects.
  3. Reducing logic errors.
  4. Moving from PHP being lossy-typed language, to kindof-strongly-typed PHP, but keeping the option to use lossy or strongly at the hands of the developers.
Loam answered 30/10, 2018 at 13:28 Comment(0)
G
3

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

Geisel answered 11/7, 2016 at 14:7 Comment(0)
C
1
  • makes you code more stable, especially if the project is large

  • the code is more readable, cleaner and professional

  • gives you autocomplete in your IDE

  • code sniffers like PHPStan can find where you are calling a method with a bad parameter

  • you can more easily understand the code and how methods are working when you come to a new project

  • without a type hint, if you called your method with the wrong object, nothing would happen because $song->title and $song->lyrics would return null; while with a type hint an exception is thrown

Cristycriswell answered 2/10, 2019 at 19:5 Comment(0)
P
0

It makes reading code predictable, like you know what type a parameter is and you know what type a function returns (if any). A lot of times when reading code that is not yours and you get to tracing yourself to a function declaration, often times you can ask yourself "wait, what is the type of parameter 1 or parameter X??" You dont want to put a debugger like var_dump() over and over again when you want to have an idea what the parameter(s) is/are.

Putumayo answered 28/5, 2023 at 15:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.