2010-06-09 2 views
5

저는 가능한 한 강력하게 입력하려고하는 프레임 워크에서 작업하고 있습니다. (저는 PHP에서 일하고 있고 C#에서 좋아하는 아이디어를 취하여이 프레임 워크 내에서 활용하려고합니다.) 도메인 엔티티/객체의 컬렉션 인 Collection 클래스를 만듭니다. 그것은 닷넷의 List<T> 객체를 모델링 한 것입니다.PHP 'instanceof'가 클래스 상수와 함께 실패했습니다.

나는이 클래스를 타이핑하는 것을 방해하는 장애물에 부딪혔다. UserCollection을 가지고 있다면 User 객체를 그 안에 넣어야합니다. PostCollection이있는 경우 Post 객체 만 허용해야합니다.

모든이 프레임 워크의 컬렉션에는 추가, 제거, 반복과 같은 특정 기본 기능이 있어야합니다. 인터페이스를 만들었지 만 다음 작업을 수행 할 수 없다는 것을 알았습니다.

interface ICollection { public function add($obj) } 
class PostCollection implements ICollection { public function add(Post $obj) {} } 

이것은 인터페이스를 위반 한 것입니다. 하지만 모든 컬렉션이 같은 유형이므로 인터페이스를 강력하게 입력 할 수 없습니다. 이 코드를 실행하려고하면

interface ICollection { public function add($obj) } 
abstract class Collection implements ICollection { const type = 'null'; } 
class PostCollection extends Collection { 
const type = 'Post'; 
public function add($obj) { 
    if(!($obj instanceof self::type)) { 
    throw new UhOhException(); 
    } 
} 
} 

, 내가 instanceof 문에 syntax error, unexpected T_STRING, expecting T_VARIABLE or '$'를 얻을 : 그래서 나는 다음 시도했다. 문제에 대한 약간의 조사와 원인의 근본 원인은 $obj instanceof self이 클래스에 대한 테스트에 유효하다는 것입니다. PHP는 표현식에 전체 self::type 상수 문장을 처리하지 않는 것으로 보입니다. self::type 변수에 괄호를 추가 예기치 않은 '('에 관한 오류가 발생했습니다.

확실한 해결 방법은 $type가 변수로 선언 된 경우 상수. 표현은 $obj instanceof $this->type 물론, (잘 작동 type 변수를 확인하지 않는 것입니다)

변수를 나중에 변경하지 못하도록 상수로 값을 정의하고 싶으므로이를 피할 수있는 방법이 필요합니다.이 방법을 달성 할 수있는 방법에 대한 생각 또는 이 점에있어서 PHP를 사용하는 데 한계가 있습니까? self::this을 "이스케이프 (escape)"하거나 캡슐화하여 PHP를 처리 할 때 PHP가 죽지 않게 할 방법이 있습니까?

업데이트 아래 의견에 따라, 나는 시도 할 무언가를 생각했습니다 - 아래 코드가 작동합니다! 누구나 1) 이것을하지 않는 이유, 2) 이것이 궁극적으로 효과가없는 이유, 또는 3) 이것을 제거하는 더 좋은 방법을 생각할 수 있습니까?

interface ICollection { public function add($obj) } 
abstract class Collection { const type = null; protected $type = self::type; } 
class PostCollection extends Collection { 
const type = 'Post'; 
public function add($obj) { 
    if(!($obj instanceof $this->type)) { 
    throw new UhOhException(); 
    } 
} 
} 

업데이트 # 2 : 생산에 위의 코드를 넣어 후에는 작동하지 않습니다 밝혀졌습니다. 테스트했을 때 어떻게 작동하는지 전혀 모르지만 전혀 작동하지 않습니다. 나는 protected 변수를 사용하고있다.

+0

은 내가 1 또는 2를 대답 생각 - 심지어 t 불구하고 그는 변수가'protected'이며, 여전히 코드에서 변경 될 수 있습니다. '$ type' 변수가 우발적으로 변경되지 않도록하는 방법으로 실제 보안을 설정할 필요가 없습니다. 내가 바라는 것은 그것에 대한 보험이었다. –

+0

올바르게 이해했다면 classof 일 때 instanceof 연산에 문자열 ($ this-> type)을 부여합니다 (http://php.net/manual/en/language.operators.type.php 참조) . 나는 당신이 대신 $ this-> type이 무엇인지를 기대하는 'is_a'를 사용해야한다고 생각한다. – gacrux

+0

진실한 진술이 아닙니다 - 연결된 페이지의 예제 # 5를보십시오. –

답변

0

이 또한 사용하여 올바르게 작동 정적 :

<?php 

interface ICollection { 
    public function add($obj); 
} 
abstract class Collection implements ICollection { 
    static protected $_type = 'null'; 
} 
class PostCollection extends Collection { 
static protected $_type = 'Post'; 
public function add($obj) { 
    if(!($obj instanceof self::$_type)) { 
    throw new UhOhException(); 
    } 
} 
} 


class Post {} 

$coll = new PostCollection(); 
$coll->add(new Post()); 

그리고 실제로, 당신은 아마 당신은 몇 가지를 해결하기 위해 get_class()을 사용해야합니다 의미, 어쨌든 Collection 클래스에 당신의 add() 방법을 정의 할 항상 어쨌든 기본 Collection 클래스를 돌려 싶은, 그래서 이것은 아마 것 self::type 또는 self::$_type와 불확실성이 작동 :

abstract class Collection implements ICollection { 
    const type = 'null'; 
    public function add($obj) { 
    $c = get_class($this); 
    $type = $c::type; 
    if(!($obj instanceof $type)) { 
    throw new UhOhException(); 
    } 
    } 
} 

class PostCollection extends Collection { 
const type = 'Post'; 
} 
class Post {} 

$coll = new PostCollection(); 
$coll->add(new Post()); 
1

은 나뿐만 아니라이 동작에 의해 놀랐어요,하지만이 작동합니다 :

$type = self::type; 
if(!($obj instanceof $type)) { 
    throw new UhOhException(); 
} 

편집 :

당신은

abstract class Collection { 
    const type = null; 
    protected $type = self::type; 
} 
class PostCollection extends Collection { 
    const type = "User"; 
    public function add($obj) { 
     if(!($obj instanceof $this->type)) { 
      throw new WhateverException(); 
     } 
    } 
} 

을 할 수하지만 당신은 complicometer 켜기있어 . 이로 인해 PostCollection의 각 인스턴스에 대해 인스턴스 $type 변수를 생성하는 데 따른 추가 오버 헤드가 있습니다. 아니요. 속성에 static을 추가 할 수 없습니다.

+0

저에게 아이디어가있었습니다 - 내 게시물을 업데이트했습니다. 감사! –

+0

@Nathan Loding 새 코드가'PHP Notice : Undefined property : PostCollection :: $ type'라고했습니다. – Artefacto

+0

오타를 만들었습니다!클래스 정의는'class PostCollection extends Collection'이어야합니다 - 잘 알려 드리겠습니다. –

3

다른 해결 방법은하는 것입니다 : 당신이 파서를 충족하기 위해 잠시 변수에 넣을 수없는 것을 의미하지 않는다 상수의

$type = self::type; 
if (!($obj instanceof $type)) 

그냥 '원인.

+0

저에게 아이디어가있었습니다 - 나는 내 게시물을 업데이트했습니다. 감사! –

+0

또는 괄호가 잘못 되었습니까? '! ($ obj instanceof (self :: type))' – seanmonstar

+0

@seanmonstar - 정확한 표현이 PHP에서 저를 위해 오류를 던졌습니다. 너에게 효과가 있었 니? '예기치 않은'(" ''. –

-2

문자열을 클래스 이름으로 기대하는 instanceof 대신 PHP의 is_a 함수를 사용해보십시오.

+0

예제 # 5 ("using instanceof 다른 변수와 함께 ") http://php.net/manual/en/language.operators.type.php. –

+0

아, 사실, 내 잘못, 당신의 의견을 주셔서 감사합니다. – gacrux

2

도메인 엔터티/개체의 컬렉션 인 Collection 클래스를 만들고 있습니다. 그것은 닷넷의 List<T> 객체를 모델링 한 것입니다.

일반적으로 한 언어를 다른 언어로 작성하는 것은 좋지 않습니다. PHP에서는 콜렉션이 필요하지 않습니다.

계속 길을 가려면 PHP에서 제공 한 도구를 사용해보십시오. 예를 들어, ArrayObject이 있습니다. 입력 된 항목 만 배열에 들어가도록 필요한 방법을 상속하거나 무시할 수 있습니다. ArrayObject는 PHP에서 일반적인 배열을 사용할 수있는 곳이라면 어디에서나 사용할 수 있습니다. 또한, 기본 비트 및 조각 이미 당신을 위해 작성되었습니다.

The rest of the Standard PHP Library은 (는) 특히 SplObjectStorage 클래스에 관심이있을 수 있습니다.

+0

나는 그것을"좀 모델 "이라고 말한 것을 제외하고 나는 동일한 유형의 여러 객체에 대한 컨테이너가 필요하며 쉽게 추가, 제거, 찾을 수 있습니다. d를 반복하고 PHP 응용 프로그램에 있습니다. 이것이 .Net 앱이라면'List '개체를 사용합니다. PHP에서는 필자 만의 변형을 만드는 즐거움이 있습니다. –

+0

첫 번째 단락을 넘어서는 글을 읽고 싶을 수도 있습니다. PHP가 어떻게 다른 언어의 구문을 구현하지 않고도이 동작을 생성하는 데 필요한 도구를 제공 할 수있는 방법을 설명합니다. :) – Charles

+2

SplObjectStorage와 ArrayObject 옵션은 내가 원하는 것만은 아니다. 나는 그들이 성취 될 수없는 기술적 이유가없는 한, 한 언어에서 다른 언어로 구성을 만들려고 시도하지 않을 이유가 없다. 이 경우 .NET에서 List 객체를 모방 한 콜렉션 클래스를 작성하는 것은 PHP 내에서 가능합니다. 강력하지 않은 유형의 부분입니다. PHP over .NET의 기쁨은 당신이 직접이 객체들을 만들 수 있다는 것입니다. 나는 다른 언어로 하나의 언어를 쓰고있는 것이 아닙니다. 저는 다른 언어로 된 경험을 바탕으로 한 언어로 가능성을 모색하고 있습니다. –

1

는 readly이

공공 기능 추가 (ICollection에의 $의 OBJ)처럼해야한다 {

} 이제 함수에 개체를 추가 즉의 인스턴스가 아닌 추가하려고하면

Icollection (예를 들어) 인스턴스를 사용하여 확인하기 전에 실패합니다.

+0

좋은 생각입니다.이 경우에는 Entity 객체이지만 좋은 토대가 될 것입니다. –

관련 문제