>백엔드 개발 >PHP7 >PHP7 유형 팁: PHP 개발자로서 항상 기억해야 할 사항

PHP7 유형 팁: PHP 개발자로서 항상 기억해야 할 사항

藏色散人
藏色散人앞으로
2020-11-01 16:46:272394검색

추천 튜토리얼: "PHP7"

이 글은 http://web-techno.net/typing-with-php-7-what-you-shouldnt-do/에서 번역되었습니다. , 원문으로 이동해주세요.

PHP7에서 강력한 타이핑이 등장했을 때 빛을 보았습니다. 마침내 나는 PHP의 약한 타이핑으로 인해 더 이상 버그나 불일치가 발생하지 않을 것이라는 확신을 갖게 되었습니다.

몇 가지 코드를 읽었던 기억이 나고 그 안에 있는 변수의 유형이 무엇인지 전혀 몰랐습니다. 이 메서드의 반환 값으로 int 유형을 사용해야 합니까? 불렌 유형? 이로 인해 숨겨진 버그나 예상치 못한 동작이 발생합니까?

엄격한 입력이 유용하며 반환 값 유형 힌트도 유용합니다. 당신은 당신이 다루고 있는 데이터가 무엇인지 정확히 알고 있습니다. 더 이상 추측할 필요가 없습니다.

그러나 이 글에서 PHP7이 나의 노력의 끝은 아닙니다. PHP7이 이 문제를 해결하기 위해 열심히 노력하더라도 여전히 난독화된 코드를 작성할 수 있습니다. 코드를 체계적으로 유지하려면 따라야 할 몇 가지 규칙이 있습니다.

이 기사의 각 예제를 실행하기 위해 PHP7.1.1-dev의 명령줄 모드를 사용하겠습니다.

PHP 유형 선언

PHP7은 스칼라 유형과 반환 값 유형이라는 두 가지 적합한 유형을 도입합니다. 여기서는 차이점과 사용 방법을 설명하지 않겠습니다. PHP 주석 초안은 나보다 더 잘할 것입니다:

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

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

PHP7은 강력한 타이핑을 가지고 있습니다... 아직도 이상해?

직설적으로 말하자면: PHP7 프로그래밍은 예측할 수 없는 결과를 가져올 수 있습니다.

이것이 의심되시나요? 다음은 몇 가지 예입니다.

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

mySuperFunction();

이 코드는 괜찮습니다. 유형 선언은 이 메서드가 int 유형을 반환해야 함을 나타냅니다. 그러나 문자열 유형을 반환합니다. 말할 것도 없이, PHP는 오류를 발생시킵니다:

치명적인 오류: Uncaught TypeError: mySuperFunction()의 반환 값은 정수 유형이어야 하며 문자열이 반환되어야 합니다. 치명적인 오류: 잡히지 않는 유형 오류: mySuper 함수의 반환 유형은 int 유형이어야 하며 문자열이 반환되었습니다.

다른 예를 살펴보겠습니다.

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

mySuperFunction();

위와 동일한 결과: 유형 오류입니다. 좋은! 반환 유형에 문제가 있나요? 내가 당신에게 거짓말을 했나요?

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

mySuperFunction();

이것은 예외를 발생시켜야 하지 않나요? 반환 유형을 int로 명확하게 정의했지만 반환되는 것은 문자열입니다.

번역 작성자가 추가합니다: PHP7.2.4에서는 알림 오류가 발생합니다:

알림: 형식이 올바르지 않은 숫자 값이 발생했습니다. 형식이 잘못된 숫자 유형 값이 발생했습니다.

오류. 이 함수는 1을 반환합니다.

function mySuperFunction():int{    return 1.1456415;
}

mySuperFunction();

는 반환 int 유형을 정의합니다. 분명히 실제 반환 유형은 float입니다. 하지만 이 코드는 예외를 발생시키지 않습니다.

1을 반환합니다.

아직 확신하지 못하시나요?

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

mySuperFunction();

PHP는 '1hello world'를 부울 유형으로 처리하고 1을 반환합니다.

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

mySuperFunction();

PHP의 이상한 세계에서 'abcde'는 부울입니다. 실제로 이 메서드는 true를 반환합니다!

보시다시피 이러한 코딩 규칙은 여전히 ​​혼란스럽습니다. 즉, 코드가 명확하더라도 사실이 아닐 수도 있습니다!

PHP 엄격한 타이핑

PHP는 약한 타이핑을 사용합니다.

하고 싶지 않아요.

실제로 PHP는 런타임에 문자열 유형을 부울 유형으로, 그리고 int 유형으로 자동 변환합니다. 코드를 엉망으로 만들었습니다! 간단하고 명확해야 할 것이 엉망이 되었습니다.

분명히 말씀드리겠습니다. 우리는 개발자입니다. 따라서 코드의 데이터 유형을 제어해야 합니다.

이렇게 하지 않으면 버그의 문이 열리게 되어 개발자들 사이에 이상한 행동과 오해가 퍼질 것입니다. 코드가 변경됩니다. 벌레가 나타나고, 상사가 당신을 해고하고, 아내가 당신에게 실망하고, 당신은 나락에 빠지게 될 것입니다. 자책감에 슬프고 외롭다.

아직 구제의 기회가 있습니다! 모든 것이 가능합니다. PHP에는 해결책이 있습니다!

엄격 유형 모드 참고:

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

이 코드를 실행하면 치명적인 오류가 발생합니다.

치명적인 오류: Uncaught TypeError: mySuperFunction()의 반환 값은 부울 유형이어야 하며 문자열이 반환됩니다!

Uncaught TypeError: mySuperFunction()의 반환 값은 부울 유형이어야 하며 문자열이 반환되었습니다!

이 오류가 화면에 나타나는 것을 보고 매우 기뻤습니다. 보통 오류가 발생하는 것은 재미없지만 이번에는 괜찮았습니다. 물론 부울 유형이 아닌 문자열 유형입니다!

제 제안은 모든 코드에 이 엄격한 유형 선언을 넣는 것입니다. 어딘가에! IDE용 코드 조각을 만듭니다. PHP 파일을 생성할 때마다 엄격한 유형 선언을 맨 위에 배치해야 합니다.

안타깝게도 엄격 모드를 전역적으로 설정할 수는 없습니다. 모든 PHP 파일에서 이 작업을 수행해야 합니다. 이유는 간단합니다. 강력한 형식의 모드를 구현할 필요가 없더라도 애플리케이션에 있는 모든 패키지 또는 기타 유형의 리소스입니다.

어떤 사람들은 동의하지 않을 것이라는 것을 알고 있습니다. 나는 어떤 사람들이 단순히 "유연성"을 위해 코드 일관성을 파괴할 준비가 되어 있다는 것을 알고 있습니다.

저는 "부울 유형을 문자열 유형으로 표현해야 한다고 주장하기 쉽습니다"라는 주장을 알고 있습니다.

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

위 내용은 PHP7 유형 팁: PHP 개발자로서 항상 기억해야 할 사항의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 luyuqiang에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제