为什么 PHP 中需要类型提示?

Why is type hinting necessary in PHP?

我无法理解类型提示在 PHP 中的重要性。

显然'type hinting'在PHP中可以这样定义:

"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.

所以最基本的类型提示,并不是真正使代码工作所必需的?

我有以下代码来尝试理解发生了什么...

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;
}

无论有没有函数 sing() 中的小类型提示,代码都会执行它的操作;

所以,这让我相信类型提示只是一种编码约定,以确保只使用某些 类 而不需要生成功能代码,这是正确的吗?

类型提示,正如上面引述的那样,如果您与团队合作,是否可以创建标准

我是不是遗漏了什么?

Type hinting 顾名思义,更多的是提示。它允许开发人员查看 类 可以作为参数传递的内容,并防止他们传递错误的参数。如果您与不止一个人在同一个项目上工作,那将特别有用 and/or 代码是开源的。

在 php7 中添加了字符串、整数、(混合)和数组的类型提示,因此您不仅需要 类,还可以使用标准的 php 类型

类型提示不是必需的,但它可以让您发现某些类型的错误。例如,您可能有一个需要整数的函数或方法。 PHP 会将 happily convert “数字字符串”转换为整数,这会导致难以调试的行为。如果您在代码中指定您特别需要一个整数,这可以首先防止这些类型的错误。许多程序员认为以这种方式保护他们的代码是最佳实践。

作为实际操作的具体示例,让我们看一下 index.php 文件的更新版本:

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);

以及我添加的新 Test.php 文件:

Test.php

<?php

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

当我 运行 index.php 现在,我得到以下错误:

输出:

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

这是 PHP 让我知道我在调用 sing() 函数时试图使用错误类型的 class。

这很有用,因为即使上面的示例有效,Test class 也可能与 Song class 不同。这可能导致以后难以调试错误。以这种方式使用提示为开发人员提供了一种在导致问题之前防止类型错误的方法。这在像 PHP 这样的语言中特别有用,这种语言通常急于在类型之间自动转换。

您的代码 运行 无论是否有类型提示都可以。

类型提示只是强制您将特定类型的内容传递给 function/method。

例如

function displayNames($names)
{
    foreach ($names as $n) {
        echo $n;
    }
}

假设用户按如下方式传入数组,此函数将正常工作。

displayNames(array('Tom', 'John', 'Frank'));

但是,PHP 将允许用户传入任何内容,例如字符串、整数、布尔值、对象等。None 这些内容在到达foreachdisplayNames 函数内部。

添加 array 类型提示强制执行此函数期望 $names 为数组的事实。

function displayNames(array $names)
{
    // We now KNOW that $names is an array.
    foreach ($names as $n) {
        echo $n;
    }
}

数组是一个简单的示例,但正如您所说,您也可以键入提示对象。在这种情况下,它允许开发人员仅接受 doSqlQuery() 方法中的数据库连接实例。

你应该知道

PHP 7 以下的版本仅允许 类(包括接口)和数组的类型提示。为了输入 stringintbool 等的提示,您需要使用 PHP 7.

类型提示是一个自然过程。乍一看,这似乎是额外的工作,但随着项目在 PHP 中的发展,它会非常有帮助。它允许更好的可读性,并使错误控制和严格的编程约定更容易应用。

最初,您必须实现“契约”,其中契约是一个 php 接口,可以“锁定”常量和关键 public 方法及其参数,例如:

interface SongInterface {
    //...
}

class Song implements SongInterface
{
    public $title;
    public $lyrics;
    //...
}

然后继续实际执行部分:

$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);

使用接口,你只需定义功能,然后在歌曲中实现它class。这样您就可以随时注入另一首歌曲 class(具有更新的功能和更改)而不会破坏您的应用程序。查看 oop 接口:http://php.net/manual/en/language.oop5.interfaces.php

从php7开始,您还可以定义函数的return类型。 https://wiki.php.net/rfc/return_types

有必要吗? 没有

这是最佳做法吗?

哪个PHP版本支持它? PHP 5.6 仅适用于 类,PHP 7+ 也允许对原语(int、string、boolean 等)进行类型提示。

它有什么用?

  1. 通过 IDE 获取提示(取决于 IDE)。
  2. 标准化团队项目中的编码风格。
  3. 减少 logic errors.
  4. 从 PHP 有损类型语言转变为强类型语言 PHP,但将使用有损或强类型的选项保留在开发人员手中。
  • 让你的代码更稳定,尤其是项目大的时候

  • 代码更易读、更简洁、更专业

  • 让您在 IDE

    中自动完成
  • PHPStan 之类的代码嗅探器可以找到您调用方法的位置 参数错误

  • 来到一个新的项目中,你可以更容易地理解代码和方法是如何工作的

  • 没有类型提示,如果你用错误的对象调用你的方法,什么也不会发生,因为 $song->title $song->lyrics 会 return null;当有类型提示时抛出异常