2017-11-17 17 views
2

시나리오 내 함수가 반환 형식 City을 가지고 말을 PHP7 타입 힌트를 사용하고PhpStorm 다른

의 확장으로 반환 형식을 인식하지.

public function getCityById(int $city_id) : City { ... } 

이 함수에서 파인더를 실행 한 결과를 반환합니다. findById() 기능이 AbstractModel를 반환하기 때문에

return $this->city_finder->findById($city_id); 

는 그러나 PhpStorm, 여기에 뿌려줍니다.

하지만 class City extends AbstractModel인데 문제가되지 않습니다. 그러나 PhpStorm은이를 인식하지 못하고 경고 문구를 강조 표시합니다.

중요 경고이므로이 유형의 경고 (검사 사용 중지)를 음소거하고 싶지 않습니다.

질문

내가 PhpStorm이 return 문은 반환 형식을 만족시킬 것을 인식 할 수 있습니까? 그것에 대해 나에게 경고 중지

/** @var City $city */ 
$city = $this->city_finder->findById($city_id); 
return $city; 

이 시점에서,하지만 것 같아 :

추가 정보를 원하시면

한 가지 해결 방법과 같이, 그것을 변수를 추출하고 주석하는 것입니다 여분의 줄은 IDE에서 경고음을 음소거하기 위해 존재하기 때문에 피해야합니다.

Finder 클래스가 모델별로 생성되기 때문에 findById() 함수는 잘못된 형식을 반환하지 못하도록 보호됩니다.

$this->city_finder = $this->orm->getFinder(City::class); 
//... 
$city = $city_finder->findById(...); 
+0

'city_finder' 클래스의'findById()'메소드의 서명을 오버라이드하고 ('class'에 대한 PHPDoc 주석에서'@ method' 태그 사용),이 메소드가 구체적인'City' 클래스를 리턴하도록 할 수 있습니다 (예 : https : //stackoverflow.com/a/43112745/783119). 또 다른 아이디어 - https://stackoverflow.com/a/44913283/783119 (여기에 적용 할 지 확실하지 않음) – LazyOne

답변

4

PHPStorm이 정확합니다.

귀하의 findById()AbstractModel을 반환하며, 귀하는 다시 시도하려는 City입니다. 경우 findById()AbstractModel에서 상속되지만 City 또는 그 자손이 아닌 다른 클래스로부터받은 경우 - PHP에서 치명적인 오류가 발생하며 PHPStorm이 경고하는 것입니다.

이미 주석을 추가하거나 if ($city instanceof City) {return $city; }을 명시 적으로 확인하여이 문제를 해결할 수 있습니다. 런타임시 안전 해지면 약간 부풀어 오르게 될 수 있습니다.

+0

실제로 Finder 클래스가 모델별로 생성되기 때문에 우리는이 문제에 대해 안전합니다. . 예 : '$ finder = $ orm-> getFinder (City :: class);'. 그러나 PHPStorm이이를 감지하는 것은 매우 어려울 것입니다. – Alec

+0

@Alec 그건 PHPStorm이 알기에 그다지 어려운 것이 아니라, 그 ORM을위한 특별한 규칙 없이는 불가능합니다. 유형 시스템이 관련되어있는 한,'City :: class'는 생성자에서 사용하는 문자열 일 뿐이며, 생성 된 객체의 유형을 변경하지 않습니다. – IMSoP

+0

@IMSoP True .. PhpStorm의 [고급 메타 데이터 기능] (https://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Advanced+Metadata)이 다른 경우를 돕고 있습니다 ...하지만 여기서는 아무 것도 할 수 없을지 모르겠습니다. (이 방법은 다르게 작동합니다 - 보이는 것처럼)'$ finder'는'City'와'Area'에 대한 동일한 클래스 인스턴스이고 내부적으로 모든 뉘앙스 (차이)를 가질 수 있습니다. – LazyOne

3

기술적으로 PHPStorm은 기술적으로 적합합니다. 함수 계약에 따라 명세서가 잘못된 값을 반환 할 수 있습니다. 우리가 $result 여기에서 알 수

$result = $this->city_finder->findById($city_id); 

있는 유일한 방법은 우리를 약속 findById 것입니다, 그것은 그것이 AbstractModel 있다고합니다. City 일 수 있지만 User 또는 Widget이거나 익명의 개체 인 class extends AbstractModel {} 일 수 있습니다.

근본적인 문제는 $this->city_finder이 일부 추상 저장소의 인스턴스라는 것입니다. 은 항상 City 개체를 처리한다는 것을 알고 있습니다. 실제로는 유형 시스템에 내장되어 있지 않습니다. 보다 구체적인 클래스 인 경우 findById 메서드에서 City 개체를 반환했으며 형식이 안전하다고 선언 할 수 있습니다.

: PHP는 "제네릭"또는 "템플릿 메타 프로그래밍"을 지원하는 경우 ORM이 매개 변수 ( $finder = $orm->getFinder(City::class);)로 클래스 이름에 걸리는 의견을 바탕으로

, 당신은 다음처럼 작성할 수
class ORM { 
    public function getFinder<T>(): Finder<T> { ... } 
} 
class Finder<T> { 
    public function findById(int $id): T { ...} 
} 
$finder = $orm->getFinder<City>(); 
$city = $finder->findById($city_id); 

$finderFinder<City>의 인스턴스 였으므로 findByIdCity을 반환합니다.

generics가 없다면, 생성자에 City::class이 주어진다면 Finder 클래스는 항상 해당 클래스의 인스턴스를 반환한다는 것을 분석기에 알릴 방법이 없습니다.