PHP 7 이전에“문자열, 문자열이 주어져야한다”를 어떻게 해결합니까?


217

내 코드는 다음과 같습니다.

function phpwtf(string $s) {
    echo "$s\n";
}
phpwtf("Type hinting is da bomb");

이 오류가 발생하는 원인은 다음과 같습니다.

잡을 수있는 치명적 오류 : phpwtf ()에 전달 된 인수 1은 문자열의 문자열이어야합니다.

PHP가 같은 호흡에서 원하는 유형을 인식하고 거부하는 것을 보는 것은 조금 Orwellian 이상입니다. 5 개의 조명이 있습니다.

PHP에서 문자열에 대한 유형 힌트와 동등한 것은 무엇입니까? 여기서 무슨 일이 일어나고 있는지 정확하게 설명하는 답변에 대한 보너스 고려.


5
글쎄, 그건 당신이 잘못하고 있기 때문입니다. 코드가 작동하지 않아야합니다. PHP 문서에서 저글링 유형을 읽으십시오. PHP는 동적 형식이고 약한 형식입니다. (문자열)을 사용하여 인수를 문자열로 캐스트 할 수 있지만 (함수 본문에서만) 코드 스 니펫에서와 같이 객체 및 배열 만 암시 할 수 있습니다.
Richard Knop

7
문제는 당신이 작은 실수를 한 것입니다. 거기 조명!
CJ 데니스

@ 고든, 나는 5.6에서 테스트했다. 아직 운이 없다.
Pacerier

@Pacerier 최신 개발 내용 은 wiki.php.net/rfc를 참조하십시오 .
Gordon

3
분명히, 스칼라 타입 힌팅 (OP는 직관적으로 위와 같은 것으로 예상 됨)은 source 에 따라 PHP * 7 *에 대한 RFC에서 최종 승인되었습니다 . 승인 된 RFC는 명백하게 매개 변수 (인수)뿐만 아니라 유형 검사 리턴 값 을 위한 구문 설탕 을 제공합니다 . 앞으로 오랜 시간이 지났습니다.
SeldomNeedy

답변:


204

PHP 7 이전에는 타입 힌트 를 사용하여 객체와 배열의 타입을 강제 할 수 있습니다. 스칼라 형식은 형식이 불가능합니다. 이 경우 클래스의 객체 string가 예상되지만 (스칼라) 제공 string합니다. 오류 메시지는 재미있을 수 있지만 처음에는 작동하지 않습니다. 다이나믹 한 타이핑 시스템을 감안할 때, 이것은 실제로 일종의 왜곡 된 의미를 갖습니다.

스칼라 유형은 수동으로 "힌트 힌트" 만 할 수 있습니다 .

function foo($string) {
    if (!is_string($string)) {
        trigger_error('No, you fool!');
        return;
    }
    ...
}

1
@deceze, 리버스 타입 힌트를위한 문법이 있습니까? 예 아무것도 하지만 배열.
Pacerier

@Pacerier 아니오, 없습니다.
deceze

4
이 답변은 PHP 7에는 유효하지 않습니다
Jose Nobile

24

에서 PHP 설명서 :

타입 힌트는 객체와 배열 (PHP 5.1부터) 타입 만 될 수 있습니다. int 및 string을 사용한 전통적인 유형 힌트는 지원되지 않습니다.

그래서 당신은 그것을 가지고 있습니다. 오류 메시지는 실제로 도움이되지 않습니다.

** 2017 년 편집 **

PHP7은 더 많은 함수 데이터 유형 선언을 도입했으며, 위에서 언급 한 링크는 함수 인수 : 유형 선언 으로 이동되었습니다 . 해당 페이지에서 :

유효한 유형

  • 클래스 / 인터페이스 이름 : 매개 변수는 지정된 클래스 또는 인터페이스 이름의 인스턴스 여야합니다. (PHP 5.0.0부터)
  • self : 매개 변수는 메소드가 정의 된 클래스와 동일한 클래스의 인스턴스 여야합니다. 이것은 클래스 및 인스턴스 메소드에서만 사용할 수 있습니다. (PHP 5.0.0부터)
  • array : 매개 변수는 배열이어야합니다. (PHP 5.1.0부터) callable이 매개 변수는 유효한 호출 가능해야합니다. PHP 5.4.0
  • bool : 매개 변수는 부울 값이어야합니다. (PHP 7.0.0부터)
  • float : 매개 변수는 부동 소수점 숫자 여야합니다. (PHP 7.0.0부터)
  • int : 매개 변수는 정수 여야합니다. (PHP 7.0.0부터)
  • string : 매개 변수는 문자열이어야합니다. (PHP 7.0.0부터)
  • iterable : 매개 변수는 Traversable의 배열 또는 인스턴스 여야합니다. (PHP 7.1.0부터)

경고

위의 스칼라 유형에 대한 별명은 지원되지 않습니다. 대신 클래스 또는 인터페이스 이름으로 취급됩니다. 예를 들어, 부울을 매개 변수 또는 리턴 유형으로 사용하려면 bool 유형이 아닌 클래스 또는 인터페이스 부울의 인스턴스 인 인수 또는 리턴 값이 필요합니다.

<?php
   function test(boolean $param) {}
   test(true);
 ?>

위의 예는 다음과 같이 출력됩니다.

 Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of boolean, boolean given, called in - on line 1 and defined in -:1

마지막 경고는 실제로 "string, string given 인수"라는 오류를 이해하는 데 실제로 중요합니다. 대부분 클래스 / 인터페이스 이름 만 인수 유형으로 허용되므로 PHP는 클래스 이름 "string"을 찾으려고하지만 기본 유형이므로 찾을 수 없으므로이 어색한 오류로 실패합니다.


8

PHP는 객체를 지정하기 위해 클래스를 제공하는 "힌팅"을 허용합니다. PHP 매뉴얼에 따르면, "타입 힌트는 객체와 배열 (PHP 5.1부터) 타입 일 수 있습니다. int와 문자열을 사용한 전통적인 타입 힌트는 지원되지 않습니다." "string"을 선택했기 때문에 오류가 혼동됩니다. "myClass"를 그 자리에 놓고 오류가 다르게 읽 힙니다. "phpwtf ()에 전달 된 인수 1은 myClass의 인스턴스 여야합니다.


3

다른 사람들이 이미 말했듯이, 유형 힌트는 현재 객체 유형에서만 작동합니다. 그러나 트리거 한 특정 오류는 다음 문자열 유형 SplString 을 준비하는 중일 수 있습니다 .

이론적으로는 문자열처럼 동작하지만 객체이므로 객체 유형 확인을 통과합니다. 불행히도 아직 PHP 5.3에는 없지만 5.4에 올 수 있으므로 테스트하지 않았습니다.


2

이러한 유형의 사용할 수 있습니다, 그래서 PHP 7.0로 유형 선언은, 스칼라 유형을 허용 : self, array, callable, bool, float, int, string. 처음 3 개는 PHP 5에서 사용할 수 있지만 마지막 4 개는 PHP 7에서 새로 추가되었습니다 . 클래스 이름으로 해석 될 다른 항목 (예 : integer또는 boolean)을 사용하는 경우 .

자세한 내용은 PHP 매뉴얼을 참조하십시오 .


0

안전하고 예쁘지 않지만 필요한 경우 :

class string
{
    private $Text;
    public function __construct($value)
    {
        $this->Text = $value;
    }

    public function __toString()
    {
        return $this->Text;
    }
}

function Test123(string $s)
{
    echo $s;
}

Test123(new string("Testing"));

5
그래도 계속 만들 수 있습니다new string(array(1,2,3))
Jimmy T.

0

Laravel Controller에서 PHP 파일로 함수를 호출 할 때이 오류가 발생했습니다.

몇 시간 후에 문제를 발견했습니다 . 정적 함수 내에서 $ this 를 사용하고있었습니다 .


Using $this when not in object context사실 은밀한 메시지입니다.
벤 프란 센

0

(원래 그의 질문 에 leepowers 에 의해 게시 됨 )

한 가지 큰 이유로 인해 오류 메시지가 혼동됩니다.

기본 유형 이름은 PHP에서 예약되지 않았습니다

다음은 모두 유효한 클래스 선언입니다.

class string { }
class int { }
class float { }
class double { }

내 실수는 오류 메시지가 문자열 기본 유형만을 참조한다고 생각하고 있었는데 '인스턴스'라는 단어가 일시 중지되어야합니다. 추가 설명을위한 예 :

class string { }
$n = 1234;
$s1 = (string)$n;
$s2 = new string();
$a = array('no', 'yes');
printf("\$s1 - primitive string? %s - string instance? %s\n",
        $a[is_string($s1)], $a[is_a($s1, 'string')]);
printf("\$s2 - primitive string? %s - string instance? %s\n",
        $a[is_string($s2)], $a[is_a($s2, 'string')]);

산출:

$ s1-기본 문자열? 예-문자열 인스턴스? 아니

$ s2-기본 문자열? 아니오-문자열 인스턴스? 예

PHP에서는 실제로 a 일 때 stringa가 string예외가 될 수 string있습니다. 암시 적 유형 변환을 사용하는 모든 언어와 마찬가지로 컨텍스트가 가장 중요합니다.


-1

내부 블록의 PHP에서 typecasting을 생각합니다 .PHP의 String은 내가 아는 것처럼 객체가 아닙니다.

<?php
function phpwtf($s) {
    $s = (string) $s;
    echo "$s\n";
}
phpwtf("Type hinting is da bomb");

2
함수에 is_string () 유효성 검사를 추가하여 다른 값이 함수에 전달되지 않도록 할 수 있습니다.
subosito

1
(string) $s$s문자열로 캐스트 할 수없는 객체 인 경우 오류가 발생할 수 있습니다 ( __toString()메소드가 구현 되지 않음 ). 그렇게 쉽지는 않습니다.
Yanick Rochon

네 야닉이 맞습니다. 그러나 모든 입력을 문자열로 강제 설정할 수는 없습니까? 그래서 예외가 발생합니다. 우리는 일종의 유효성 검사를 결합하고 나머지에 대한 예외를 잡을 수 있습니다.)
subosito

나는 예외를 잡는 것이 비용이 많이 들고 나쁜 디자인 패턴 / 코딩 습관으로 이어지기 때문에 변수를 캐스팅 할 수 있는지 먼저 확인하지 않고 문자열에 일부 변수를 캐스팅하는 것을 피해야한다고 말하고 있습니다.
Yanick Rochon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.