Home  >  Article  >  Backend Development  >  Mastering PHP: Type Hinting techniques

Mastering PHP: Type Hinting techniques

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-10-05 06:17:30893browse

Mastering PHP: Type Hinting techniques
Photo by ???? ??? on Unsplash

Type hinting is considered by some to be the holy grail of features. One that all programming languages must have. PHP for the longest time didn’t have such a system but has now been adopted widely by most developers.

That said, PHP’s type system doesn’t go as far as other languages. Many implement what are known as Generics. This is the ability to enforce a type among structures and Collections. For instance, in Java we can specify that Arrays must only contain items of a certain type, for example, an Array of Strings.

Maybe someday we’ll have this functionality in PHP as well, but until then we can actually solve this with a few different techniques. For a lack of a better description, I refer to these as Soft Type hints and Runtime hints.

Type Hints

The first and most obvious type hints are the ones introduced in PHP 7 and are still being added to PHP. Type-hinted constants were only added in PHP 8.3.

Type hints are useful to help convey what needs to be passed to a method or function as a parameter or what that method will return. Type hints are going to affect the signatures of any classes they use them with as extending a class with type hints already established will mean they can’t be overridden.

An example of a class that makes full use of types would be:


<?php

class Foo
{
    public function bar(array $strings): \Closure
    {
       return function (string $string) use ($strings): bool {
           return in_array($string, $strings);
       };
    }
}


There are, of course, limitations in our type hints because as previously mentioned, we can’t conform an array to be all of the same type and instead we must just use array . We also can’t constrain numbers to being only positive or within a certain range.

Another one can be Closures as there’s no way to describe anonymous functions within PHP’s native types. Instead, we must either use Closure or callable . Often callable isn’t allowed to be used as a type as well.

Luckily, there’s still a way to describe these more complicated scenarios with type hints.

Soft Type Hints

Our next kinds of type hints are supplied via PHPDocs. While native types will throw exceptions during run time if a method is passed or returns the wrong type, PHPDoc type hints have no effect on the runtime of the application.

Instead, soft type hints help us purely when we’re using an IDE such as VS Code or PHPStorm, which will detect those types for us. The other use case is with static analysis tools like PHPStan and subsequently Rector.

The biggest advantage of using soft types is that it allows you to describe with more precision the type of any parameters, properties, etc. For instance, we can take the previous class and make it easier to understand the arrays or closures used.


<?php

class Foo
{
    /**
     * @param string[] $strings
     * @return \Closure(string): bool
     */
    public function bar(array $strings): \Closure
    {
       return function (string $string) use ($strings): bool {
           return in_array($string, $strings);
       };
    }
}


The best way to make sure all your type usage is correct is to install PHPStan. From there you’ll likely need to use at least level 5. This can then be enforced through continuous integration steps that check the type hinting is correct.

There’s actually a list you can use if you want to use the correct soft type hint. Even better, there’s a PHPStan tool you can use to test if all the type hinting it correct per PHPStan if you’re unsure and want to run a quick test.

Runtime Hints

Our next way of supporting types is to use runtime hints. What this actually means is executing our own code to check the types from parameters. For instance, we can check if an array only contains a particular type of object. If it doesn’t, then we throw an InvalidArgumentException.


<?php

/**
 * @param string[] $foo
 */
function bar(array $foo) {
    foreach ($foo as $string) {
        if (! is_string($string)) {
            throw new \InvalidArgumentException('foo contains non-string value');
        }
    }

    // rest of the code
}


By the way, this technique is sometimes referred to as defensive programming. Looking at the code example, this is pretty cumbersome. It’s a lot of code just to simply check if an array is correct. That’s why we often resort to a library instead, in this case webmozart/assert .


composer require webmozart/assert


Now with this package installed we can shorten this down to a simple one-liner.


<?php

use Webmozart\Assert;

/**
 * @param string[] $foo
 */
function bar(array $foo) {
    Assert::allStrings($foo);
}


One of the great things about this library is if you add the Assert extension to PHPStan, this will help your type coverage when the code is analysed.

结论

总之,掌握 PHP 中的类型提示对于希望编写干净、可维护且可靠的代码的开发人员来说是一项基本技能。虽然 PHP 的类型系统仍然缺乏其他语言中的一些功能,例如泛型,但有多种策略可以强制执行更严格的类型——无论是通过本机类型提示、PHPDoc 注释还是运行时检查。利用 PHPStan 等工具和 Assert 等库可以帮助您确保类型安全,即使在复杂的场景中也是如此。通过将这些技术集成到您的开发工作流程中,您将能够更好地自信而精确地处理 PHP 的动态特性。

我是 Peter Fox,一位在英国使用 Laravel 的软件开发人员。感谢您阅读我的文章,我还有更多内容可以阅读 https://articles.peterfox.me。我现在也是 GitHub 上的赞助者。如果您想鼓励我写更多这样的文章,请考虑一次性捐款。

The above is the detailed content of Mastering PHP: Type Hinting techniques. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn