문자열로 PHP 클래스 속성 가져 오기


139

문자열을 기반으로 PHP에서 속성을 얻는 방법은 무엇입니까? 전화하겠습니다 magic. 그래서 무엇 magic입니까?

$obj->Name = 'something';
$get = $obj->Name;

마치 ...

magic($obj, 'Name', 'something');
$get = magic($obj, 'Name');

답변:


241

이렇게

<?php

$prop = 'Name';

echo $obj->$prop;

또는 클래스를 제어 할 수있는 경우 ArrayAccess 인터페이스를 구현 하고이 작업을 수행하십시오.

echo $obj['Name'];

첫 번째 옵션보다 두 번째 옵션을 사용하면 어떤 이점이 있습니까?
Clox

2
@Clox 일반적으로, 배열과 같은 방식으로 변수를 소비하는 기존 시스템이 있지만 객체가 제공하는 유연성과 성능을 원할 경우 후자를 사용하면 가장 큰 이점이 있습니다. 클래스를 구현하는 경우 ArrayAccess, Countable및 반복자 인터페이스 중 하나, 그것은 정상에서 대부분 구별이다array()
피터 베일리

158

중간 변수를 만들지 않고 속성에 액세스하려면 다음 {}표기법을 사용하십시오 .

$something = $object->{'something'};

또한 예를 들어 루프에서 속성 이름을 만들 수 있습니다.

for ($i = 0; $i < 5; $i++) {
    $something = $object->{'something' . $i};
    // ...
}

8
이것은 배열 값에 액세스하려는 경우 유일한 방법입니다 $this->{$property}[$name]. 그렇지 않으면 $this->$property[$name]오류가 발생합니다
goyote

@goyote : 값과 PHP 버전에 따라 다릅니다. 5.3에서는 여전히 유효한 PHP 구문이므로 "오류"가 아닌 속성을 찾을 수 없기 때문에 E_NOTICE를 트리거합니다. 그것은있을 가능성 $this->$property[$name]이 버그가 수 있도록 가능성이 있지만, 힘이 실제로 성공. $name자동으로 정수로 캐스트됩니다. 숫자가 아닌 문자열의 경우이 값은 0입니다. 그런 다음이 값의 문자열 색인$property특성 이름으로 사용됩니다. 경우 $property값이 "ABC"를 보유하고,이는 속성을 참조합니다 $this->a(인덱스 0). 그러한 속성이 있으면 성공합니다.
MrWhite

@goyote : 그러나 PHP 5.4에서 숫자가 아닌 문자열 인덱스는 자동으로 정수 0으로 캐스트되지 않으며 E_WARNING을 트리거합니다.
MrWhite

13

당신이 요구하는 것은 Variable Variables 입니다. 문자열에 변수를 저장하고 다음과 같이 액세스하면됩니다.

$Class = 'MyCustomClass';
$Property = 'Name';
$List = array('Name');

$Object = new $Class();

// All of these will echo the same property
echo $Object->$Property;  // Evaluates to $Object->Name
echo $Object->{$List[0]}; // Use if your variable is in an array

3
변수 변수는 또 다른 것입니다.
Ólafur Waage

2
문제는 이름이 문자열 (변수)에 포함될 때 클래스 속성 (변수)을 얻는 방법입니다. 아니면 질문을 잘못 읽었습니까?
matpie

8

이 같은? 테스트하지는 않았지만 정상적으로 작동합니다.

function magic($obj, $var, $value = NULL)
{
    if($value == NULL)
    {
        return $obj->$var;
    }
    else
    {
        $obj->$var = $value;
    }
}

2
+1, 문자열을 사용하여 객체 속성에 액세스 할 수 있다는 것을 몰랐습니다.
Marco Demaio

5

속성 이름을 변수에 저장하고 변수를 사용하여 속성에 액세스하십시오. 이처럼 :

$name = 'Name';

$obj->$name = 'something';
$get = $obj->$name;


4

$ obj-> {$ obj-> Name}은 중괄호가 변수를 변수처럼 속성을 래핑합니다.

이것은 최고 검색이었습니다. 그러나 $ this를 사용하는 내 질문을 해결하지 못했습니다. 중괄호를 사용하는 환경의 경우에도 도움이되었습니다 ...

Code Igniter를 사용한 예제 인스턴스 가져 오기

부모 클래스 인스턴스가있는 소스 라이브러리 클래스에서

$this->someClass='something';
$this->someID=34;

부모 인스턴스와 함께 다른 클래스에서 소스 해야하는 라이브러리 클래스

echo $this->CI->{$this->someClass}->{$this->someID};

2

추가로 : 이렇게하면 다른 방법으로는 사용할 수없는 이름으로 속성에 액세스 할 수 있습니다

$ x = 새로운 StdClass;

$ prop = 'ab'; $ x-> $ prop = 1; $ x-> { 'x y'} = 2; var_dump ($ x);

object (stdClass) # 1 (2) {
  [ "a b"] =>
  int (1)
  [ "x y"] =>
  int (2)
}
(필요하지는 않지만 필요한 경우).
더 멋진 물건을 만들고 싶다면 반성을 들여다 봐야 합니다.


1

다른 사람이 알려지지 않은 깊이의 깊은 속성을 찾으려면 모든 어린이의 모든 알려진 속성을 반복하지 않고도 아래를 생각해 냈습니다.

예를 들어 $ Foo-> Bar-> baz 또는 $ Foo-> baz 또는 $ Foo-> Bar-> Baz-> dave를 찾으려면 여기서 $ path는 'foo / bar / baz'와 같은 문자열입니다.

public function callModule($pathString, $delimiter = '/'){

    //split the string into an array
    $pathArray = explode($delimiter, $pathString);

    //get the first and last of the array
    $module = array_shift($pathArray);
    $property = array_pop($pathArray);

    //if the array is now empty, we can access simply without a loop
    if(count($pathArray) == 0){
        return $this->{$module}->{$property};
    }

    //we need to go deeper
    //$tmp = $this->Foo
    $tmp = $this->{$module};

    foreach($pathArray as $deeper){
        //re-assign $tmp to be the next level of the object
        // $tmp = $Foo->Bar --- then $tmp = $Bar->baz
        $tmp = $tmp->{$deeper};
    }

    //now we are at the level we need to be and can access the property
    return $tmp->{$property};

}

그런 다음 다음과 같이 호출하십시오.

$propertyString = getXMLAttribute('string'); // '@Foo/Bar/baz'
$propertyString = substr($propertyString, 1);
$moduleCaller = new ModuleCaller();
echo $moduleCaller->callModule($propertyString);

0

여기 내 시도가 있습니다. 일반적인 '어리 석음'체크가 내장되어있어 사용할 수없는 멤버를 설정하거나 얻지 마십시오.

이러한 'property_exists'검사를 각각 __set 및 __get으로 이동하고 magic () 내에서 직접 호출 할 수 있습니다.

<?php

class Foo {
    public $Name;

    public function magic($member, $value = NULL) {
        if ($value != NULL) {
            if (!property_exists($this, $member)) {
                trigger_error('Undefined property via magic(): ' .
                    $member, E_USER_ERROR);
                return NULL;
            }
            $this->$member = $value;
        } else {
            if (!property_exists($this, $member)) {
                trigger_error('Undefined property via magic(): ' .
                    $member, E_USER_ERROR);
                return NULL;
            }
            return $this->$member;
        }
    }
};

$f = new Foo();

$f->magic("Name", "Something");
echo $f->magic("Name") , "\n";

// error
$f->magic("Fame", "Something");
echo $f->magic("Fame") , "\n";

?>

0

이 함수는 자식 클래스의이 클래스에 속성이 있는지 확인하고, 그렇지 않으면 값을 가져 오면 null을 반환합니다. 이제 속성이 선택적이고 동적입니다.

/**
 * check if property is defined on this class or any of it's childes and return it
 *
 * @param $property
 *
 * @return bool
 */
private function getIfExist($property)
{
    $value = null;
    $propertiesArray = get_object_vars($this);

    if(array_has($propertiesArray, $property)){
        $value = $propertiesArray[$property];
    }

    return $value;
}

용법:

const CONFIG_FILE_PATH_PROPERTY = 'configFilePath';

$configFilePath = $this->getIfExist(self::CONFIG_FILE_PATH_PROPERTY);

-6
$classname = "myclass";
$obj = new $classname($params);

$variable_name = "my_member_variable";
$val = $obj->$variable_name; //do care about the level(private,public,protected)

$func_name = "myFunction";
$val = $obj->$func_name($parameters);

왜 편집 : before : eval (evil) 사용 after : 전혀 평가 없음. 이 언어로 오래된 것입니다.


이것은 매우 나쁜 조언입니다. eval () 함수는 매우 위험한 도구이며 주입 공격에 크게 취약합니다. blog.highub.com/php/php-core/php-eval-is-evil에서 정보를 제공해야합니다.
ridecar2

3
이 답변을 삭제하면 배지가 생깁니다!
Thermech
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.