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

为什么PHP中需要类型暗示?,php,oop,type-hinting,Php,Oop,Type Hinting,我很难理解PHP中类型暗示的重要性 显然,PHP中的“类型暗示”可以定义如下: “类型暗示”强制您只传递特定类型的对象。 这将阻止您传递不兼容的值,并创建 如果你与一个团队合作等,则为标准 那么,在最基本的层面上,类型暗示并不是使代码真正工作所必需的吗 我有以下代码来尝试和理解正在发生的事情 Index.php <?php include 'Song.php'; $song_object = new Song; $song_object->title = "Beat it!";

我很难理解PHP中类型暗示的重要性

显然,PHP中的“类型暗示”可以定义如下:

“类型暗示”强制您只传递特定类型的对象。 这将阻止您传递不兼容的值,并创建 如果你与一个团队合作等,则为标准

那么,在最基本的层面上,类型暗示并不是使代码真正工作所必需的吗

我有以下代码来尝试和理解正在发生的事情

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

class Song
{
    public $title;
    public $lyrics;
}
<?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);
<?php

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

类型暗示就像名字更像是一种暗示。它允许开发人员查看哪些类可以作为参数传递,并防止他们传递错误的参数。如果你与不止一个人在同一个项目中工作,并且/或者代码是用于开源的,那么这将特别有用


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

不需要类型提示,但它可以让您捕获某些类型的错误。例如,您可能有一个需要整数的函数或方法。PHP将“数字字符串”转换为整数,这会导致难以调试的行为。如果您在代码中指定您特别需要一个整数,这首先可以防止这些类型的错误。许多程序员认为以这样的方式保护他们的代码是最好的实践。 作为一个具体的例子,让我们看看
index.php
文件的更新版本:

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

class Song
{
    public $title;
    public $lyrics;
}
<?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);
<?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
唱一首叫Beat it的歌 谁对谁错并不重要。。。
快打

PHP可捕获致命错误:传递给sing()的参数1必须 是Song的一个实例,是给定测试的一个实例,在上的Test/index.php中调用 第22行,并在第15行的test/index.php中定义 可捕获致命错误:传递给sing()的参数1必须是的实例 Song是给定测试的实例,在第22行的Test/index.php中调用并定义 在test/index.php的第15行
这是PHP让我知道,当我调用
sing()
函数时,我试图使用错误的类类型


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

您的代码在有或没有类型提示的情况下都能运行良好

类型提示只是强制您将特定类型的内容传递给该函数/方法

例如

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

displayNames(array('Tom', 'John', 'Frank'));
但是,PHP允许用户传入任何内容,例如字符串、int、bool、object等。当它到达
displayNames
函数内部的
foreach
时,这些内容都不会起到预期的作用

添加
数组
类型提示将强制执行以下事实:此函数预期
$names
为数组

function displayNames(array $names)
{
    // We now KNOW that $names is an array.
    foreach ($names as $n) {
        echo $n;
    }
}
数组是一个简单的示例,但正如您所述,您也可以键入提示对象。在这种情况下,它允许开发人员仅接受
doSqlQuery()
方法中的数据库连接实例

你应该知道


低于7的PHP版本只允许类(包括接口)和数组的类型提示。要为
string
int
bool
等键入提示,您需要使用PHP7。

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

首先,您必须实现“契约”,契约是一个php接口,可以“锁定”常量和密钥公共方法及其参数,例如:

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);
$song=(对象)新歌;
$song->title=(字符串)“打败它!”;
$song->歌词=(字符串)“谁错谁对都不重要……只要打败它!”;
函数sing(SongInterface$song):字符串
{
$html=(字符串)“唱名为“..$song->title”的歌曲
.“”$歌曲->歌词。”

”; 返回htmlentities($html,entu引号,'utf-8'); } 回声唱($歌);
使用接口,您只需定义函数,然后在song类中实现它。通过这种方式,您可以始终插入另一个song类(具有更新的功能和更改),而不会中断您的应用程序。查看oop接口:


从php7开始,您还可以定义函数的返回类型

有必要吗

这是最佳实践吗

哪个PHP版本支持它?PHP5.6仅适用于类,PHP7+还允许对原语(int、string、boolean等)进行类型暗示

它有什么用处

  • 通过IDE获取提示(取决于IDE)
  • 标准化团队项目中的编码风格
  • 减少
  • 从PHP是有损类型的语言转变为某种强类型的PHP,但将使用有损或强类型的选项保留在开发人员手中
    • 使您的代码更加稳定,尤其是在项目较大的情况下

    • 代码更具可读性、更清晰、更专业

    • 让您在IDE中自动完成

    • 像phpstan这样的代码嗅探器可以在调用方法的地方找到 有错误的参数

    • 您可以更容易地理解代码和方法的用法