Home  >  Article  >  Backend Development  >  PHP7 Type Tips: What you should always remember as a PHP developer

PHP7 Type Tips: What you should always remember as a PHP developer

藏色散人
藏色散人forward
2020-11-01 16:46:272348browse

Recommended tutorial: "PHP7"

This article is translated from http://web-techno.net/typing-with-php-7-what-you-shouldnt -do/, if you are good at English, please go to the original text.

When strong typing appeared in PHP7, I saw the light. I finally feel confident that I will no longer see bugs or inconsistencies due to PHP's weak typing.

I remember reading some code and I had no idea about the type of the variables in it. Should I use int type as the return value for this method? boolen type? Will this create some hidden bugs or unforeseen behavior?

Strict typing is useful, as are return value type hints. You know exactly what data you are dealing with. You no longer have to guess.

However, PHP7 is not the end of my efforts in this article. You can still write obfuscated code, even though PHP7 works hard to fix this problem. There are some rules you need to follow to keep your code organized.

I will use the command line mode of PHP7.1.1-dev to run each example in this article.

PHP type declaration

PHP7 introduces two suitable types: scalar types and return value types. I won't explain their differences and how to use them here. PHP comment draft will do better than me:

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

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

PHP7 has strong typing...or is it weird?

Let’s be straightforward: PHP7 programming may have some unpredictable results.

Doubt this? Here are some examples:

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

mySuperFunction();

This code is fine. The type declaration indicates that this method should return type int. However, it returns string type. Needless to say, PHP will throw an error:

Fatal error: Uncaught TypeError: Return value of mySuperFunction() must be of the type integer, string returned. Fatal error: Uncaught type error: the return type of mySuper function must be of type int, a string was returned.

Let's look at another example:

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

mySuperFunction();

Same result as above: type error. good! Is there anything wrong with the return type? Did I lie to you?

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

mySuperFunction();

Shouldn’t this throw an exception? We clearly defined the return type as int, but what is returned is a string.

Translation author’s supplement: PHP7.2.4 will throw a notice error:

Notice: A non well formed numeric value encountered A poorly formatted numeric type value

error occurred. The function returns 1.

function mySuperFunction():int{    return 1.1456415;
}

mySuperFunction();

Define the return int type. Obviously, the actual return type is float. But this code does not throw exception.

It returns 1.

Still not convinced?

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

mySuperFunction();

PHP will treat '1hello world' as a Boolean type and return 1.

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

mySuperFunction();

In the weird world of PHP, 'abcde' is a boolean. Indeed, this method will return true!

As you can see, these coding rules still make you confused. In short, even if the code is clear, it may not be true!

PHP strict typing

PHP is accustomed to weak typing.

I do not want to.

In fact, PHP will silently convert the string type to the Boolean type and into the int type at runtime. Just messing up your code! Something that should be simple and clear is messed up.

Let’s be clear. We are developers. Therefore we should control the type of data in the code.

If we don't, we will open the door to bugs, spreading strange behavior and misunderstandings among developers. The code will change. Bugs will appear, your boss will fire you, your wife will be disappointed in you, and you will fall into the abyss. Sad and lonely in self-blame.

There is still a chance for redress! All things are possible. PHP has a solution!

Note strict type mode:

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

Run this code, you will get a fatal error:

Fatal error: Uncaught TypeError: Return value of mySuperFunction() must be of the type boolean, string returned!

Uncaught type error: the return value of mySuperFunction() must be of the type boolean, string returned!

I was very happy to see this error pop up on the screen. It's usually not nice to encounter errors, but this time it was okay. Of course it's a string type and not a boolean type!

My suggestion is: put this strict type declaration in every piece of code. Anywhere! Create a code snippet for your IDE. Every time you create a PHP file, you should put the strict type declaration at the top.

Unfortunately you cannot set strict mode globally. You need to do it in every PHP file. The reason is simple: any package or other type of resource in your application, even if it does not need to implement the strongly typed mode.

I know some people will disagree. I know some people are ready to destroy code consistency simply for the sake of possible "flexibility".

I know the argument: "It's easy to argue that boolean types need to be represented as string types."

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

The above is the detailed content of PHP7 Type Tips: What you should always remember as a PHP developer. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:luyuqiang. If there is any infringement, please contact admin@php.cn delete