Maison  >  Article  >  développement back-end  >  Astuces de type PHP7 : ce dont vous devez toujours vous souvenir en tant que développeur PHP

Astuces de type PHP7 : ce dont vous devez toujours vous souvenir en tant que développeur PHP

藏色散人
藏色散人avant
2020-11-01 16:46:272362parcourir

Tutoriel recommandé : "PHP7"

Cet article est traduit de http://web-techno.net/typing-with-php-7-what-you -ne devrait pas -do/, si vous êtes bon en anglais, veuillez consulter le texte original.

Lorsque le typage fort est apparu dans PHP7, j'ai vu la lumière. Je suis enfin sûr de ne plus voir de bugs ou d'incohérences dus à la faiblesse du typage de PHP.

Je me souviens avoir lu du code et je n'avais aucune idée du type que devraient être les variables. Dois-je utiliser le type int comme valeur de retour pour cette méthode ? type booléen ? Cela créera-t-il des bugs cachés ou un comportement imprévu ?

Une saisie stricte est utile, tout comme les indications de type de retour. Vous savez exactement de quelles données vous traitez. Vous n'avez plus besoin de deviner.

Cependant, PHP7 n'est pas la fin de mes efforts dans cet article. Vous pouvez toujours écrire du code déroutant, même si PHP7 travaille dur pour résoudre ce problème. Vous devez suivre certaines règles pour garder votre code organisé.

Je vais exécuter chaque exemple de cet article en utilisant le mode ligne de commande de PHP7.1.1-dev.

Déclaration de type PHP

PHP7 introduit deux types appropriés : les types scalaires et les types de valeur de retour. Je n'expliquerai pas leurs différences et comment les utiliser ici. Le brouillon de commentaire PHP fera mieux que moi :

*https://wiki.php.net/rfc/scalar_type_hints_v5

*https://wiki.php.net/rfc /return_types

PHP7 a un typage fort... ou est-ce bizarre ?

Soyons simples : la programmation PHP7 peut avoir des résultats imprévisibles.

Vous en doutez ? Voici quelques exemples :

function mySuperFunction(): int{    return "hello world";
}

mySuperFunction();

Ce code est très bien. La déclaration de type indique que cette méthode doit renvoyer le type int. Cependant, il renvoie le type de chaîne. Inutile de dire que PHP génère une erreur :

Erreur fatale : Uncaught TypeError : La valeur de retour de mySuperFunction() doit être du type entier, chaîne renvoyée. Erreur fatale : Erreur de type non interceptée : le type de retour de la fonction mySuper doit être de type int, une chaîne a été renvoyée.

Regardons un autre exemple :

function mySuperFunction():int{    return "hello world1";
}

mySuperFunction();

Même résultat que ci-dessus : mauvais type. bien! Y a-t-il un problème avec le type de retour ? Est-ce que je t'ai menti ?

function mySuperFunction():int{    return "1hello world";
}

mySuperFunction();

Cela ne devrait-il pas générer une exception ? Nous avons clairement défini le type de retour comme int, mais ce qui est renvoyé est une chaîne.

L'auteur de la traduction ajoute : PHP7.2.4 générera une erreur de notification :

Remarque : une valeur numérique non bien formée a été rencontrée Une erreur de valeur de type numérique

mal formatée s'est produite. La fonction renvoie 1.

function mySuperFunction():int{    return 1.1456415;
}

mySuperFunction();

définit le type de retour int. Évidemment, le type de retour réel est float. Mais ce code ne lève pas d'exception.

Il renvoie 1.

Toujours pas convaincu ?

function mySuperFunction():bool{    return "1hello world";
}

mySuperFunction();

PHP traitera '1hello world' comme un booléen et renverra 1.

function mySuperFunction():bool{     return "abcde";
}

mySuperFunction();

Dans le monde étrange de PHP, 'abcde' est un booléen. En effet, cette méthode retournera vrai !

Comme vous pouvez le constater, ces règles de codage vous déroutent encore. Bref, même si le code est clair, il se peut qu’il ne soit pas vrai !

Typage strict PHP

PHP est habitué au typage faible.

Je ne veux pas.

En fait, PHP convertira silencieusement le type chaîne en type booléen et en type int au moment de l'exécution. Je gâche juste ton code ! Quelque chose qui devrait être simple et clair est foiré.

Soyons clairs. Nous sommes des développeurs. Nous devons donc contrôler le type de données dans le code.

Si nous ne le faisons pas, nous ouvrirons la porte à des bugs, propageant des comportements étranges et des malentendus parmi les développeurs. Le code va changer. Des bugs apparaîtront, votre patron vous licenciera, votre femme sera déçue de vous et vous tomberez dans l'abîme. Triste et seul dans l'auto-accusation.

Il y a encore une chance de se faire pardonner ! Tout est possible. PHP a une solution !

Notez le mode de type strict :

declare(strict_types=1);function mySuperFunction(): bool{        return 'abcde';
}echo mySuperFunction();

Exécutez ce code et vous obtiendrez une erreur fatale :

Erreur fatale : Uncaught TypeError : valeur de retour de mySuperFunction() doit être du type booléen, chaîne renvoyée !

Erreur de type non détecté : la valeur de retour de mySuperFunction() doit être du type booléen, chaîne renvoyée !

J'étais très heureux de voir cette erreur apparaître à l'écran. Ce n'est généralement pas amusant de rencontrer des erreurs, mais cette fois, tout s'est bien passé. Bien sûr, c'est un type chaîne et non un type booléen !

Ma suggestion est la suivante : mettez cette déclaration de type stricte dans chaque morceau de code. N'importe où! Créez un extrait de code pour votre IDE. Chaque fois que vous créez un fichier PHP, vous devez placer la déclaration de type stricte en haut.

Malheureusement, vous ne pouvez pas définir le mode strict globalement. Vous devez le faire dans chaque fichier PHP. La raison est simple : n'importe quel package ou autre type de ressource dans votre application, même s'il n'a pas besoin d'implémenter le mode fortement typé.

Je sais que certaines personnes ne seront pas d’accord. Je sais que certaines personnes sont prêtes à détruire la cohérence du code simplement au nom d'une éventuelle "flexibilité".

Je connais l'argument : "Il est facile de prétendre que les types booléens doivent être représentés sous forme de types de chaîne."

我会回复他们:修复你的结构和/或你的实现。如果代码是弱类型,就会有一些问题。如果你确实需要,请修复真实存在的问题,不用再徘徊于把布尔值作为一个字符串或者int类型。

你是开发者。你不是黑客。你要解决问题,而不是与问题为伍。

五个字概括:强类型骄傲!PHP7是强类型类型语言了!

PHP7.1中Nullable类型 请小心nullable类型的笑里藏刀!它是猛兽!

nullabla类型详见PHP意见征求稿

你怎么会用错?

declare(strict_types=1);class User{    //Value object}class UserRepository{    private $database;    public function construct(Database $database){        $this->database = $database;
    }    public function getUserById(int $id):?User    {        //If user is not in the database, return null
        $user = $this->database->fetchUser($id);        return $user;
    }
}class EmailSender{    public function sendEmailToUser(int $userId)    {
        $userRepository = new UserRepository(new Database());
        $user = $userRepository->getUserById($userId);        //Can send email to... null!        $this->sendEmail($user);
    }
}

$emailSender = new EmailSender();
$emailSender->sendEmailToUser(12345);

这段代码将会崩溃,因为我们试图获取数据库中不存在的User模型。我们怎么能给null发邮件?

很明显你应该用如下方法修正:

...class EmailSender{    public function sendEmailToUser($userId)    {
        $userRepository = new UserRepository(new Database());
        $user = $userRepository->getUserById($userId);        if ($user !== null) {            $this->sendEmail($user);
        }
    }
}

但是这个方法有两个问题:

对nullable的处理将导致判断是否为null的判断到处都是(if ($methodReturn !== null))。无用且聒噪。

如果用户不存在以上代码将会静静地失败。「为什么用户没收到邮件?」将会是你的噩梦。你需要明白:

  • 用户模型不存在(可能是一个错误的用户id被传入了getUserByid())

  • 用户模型为null,可能因为nullable类型

  • 加上null的条件判断,导致应用什么都没做

这是另一种方式:

...class UserRepository{    private $database;    public function construct($database){        $this->database = $database;
    }    public function getUserById($id):User    {
        $user = $this->database->fetchUser($id);        //If user is not in the database, an error will be thrown!        return $user;
    }
}
...

在这个例子中没必要使用nullalble类型。代码将会抛出一个异常。如果User模型不存在,应用的执行将会终止。

那时你仅需要去处理这个错误。简单、清晰、高效,毋庸置疑。

PHP中nullable类型和接口

nullable类型有一些其他的意外。

declare(strict_types=1);interface MySuperInterface{    public function superFunction():?int;
}class SuperClass implements mySuperInterface{    public function superFunction():int    {        return 42;
    }
}

$superClass = new SuperClass();echo $superClass->superFunction();

Super类实现了接口MySubper,但不会实现接口约定。接口要求返回nullable的类型,实际将返回int类型。

然而,这段代码在PHP7.1中不会抛出错误。

等等。。。我们需要如接口中表示的那样无论如何都要返回null?

让我们尝试一下:

declare(strict_types=1);interface MySuperInterface{    public function superFunction():?int;
}class SuperClass implements mySuperInterface{    public function superFunction():int    {        return null;
    }
}

$superClass = new SuperClass();echo $superClass->superFunction();

结果如下:

Fatal error: Uncaught TypeError: Return value of SuperClass::superFunction() must be of the type integer, null returned 致命错误:未捕获的类型错误:Super类的super方法的返回值必须得是int类型,返回了null

现在我应该理解了在某场景下很有用,比如不能在数据库中存null值时。

我强烈建议你谨慎使用。我很少在代码中使用这个类型,因为我通常有更好的解决办法。

我更喜欢在大多场景下使用null对象代替null。为什么?简而言之,因为我讨厌在任何时候检测变量是否为null!

长话短说:一定要小心

我喜欢PHP。尤其当它引入了强类型。可能还不完美,但是将会越来越好。

不过当你在PHP中操作类型时,一定要多加小心。我还是要强调:

  • 需要使用严格类型。

  • 需要控制应用中数据。

  • 如果仍使用弱类型,将会是个问题。因此:修复它!

  • 不应该猜测变量的类型到底是什么。

  • 尽可能避免使用nullable类型

为了每个使用我们的代码的开发人员,我们需要保持一致性。对我来说,意味着很专业。

很明显在留言中阅读你们的建议使我很开心。

参考:

http://web-techno.net/typing-with-php-7-what-you-shouldnt-do/

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer