2009-04-30 43 views
107

Làm cách nào để nhận thuộc tính trong PHP dựa trên chuỗi? Tôi sẽ gọi nó là magic. Vì vậy, magic là gì?Nhận thuộc tính lớp PHP theo chuỗi

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

sẽ như thế nào ...

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

Trả lời

188

Như thế này

<?php 

$prop = 'Name'; 

echo $obj->$prop; 

Hoặc, nếu bạn có thể kiểm soát lớp, thực hiện các giao diện ArrayAccess và chỉ làm điều này

echo $obj['Name']; 
+0

Cảm ơn một bó! –

+1

Nội dung thú vị +1 và cảm ơn! –

+0

Bất kỳ lợi ích nào của việc sử dụng tùy chọn thứ hai trong lần đầu tiên? – Clox

7

Điều gì đó tương tự điều này? Đã không thử nghiệm nó nhưng nên làm việc tốt.

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

bình thường. –

+1

+1, không biết thuộc tính đối tượng có thể được truy cập bằng chuỗi. –

+0

Biến biến - http://php.net/manual/en/language.variables.variable.php –

5

Chỉ lưu tên thuộc tính trong một biến và sử dụng biến để truy cập thuộc tính. Như thế này:

$name = 'Name'; 

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

Điều bạn đang hỏi về được gọi là Variable Variables. Tất cả bạn cần làm là lưu trữ chuỗi của bạn trong một biến và tiếp cận nó như vậy:

$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 
+2

Biến biến là một điều khác. –

+1

Câu hỏi đặt ra là làm thế nào để có được một thuộc tính lớp (biến) khi tên được chứa trong một chuỗi (biến). Hay tôi đã đọc sai câu hỏi? – matpie

2

Cũng giống như một sự bổ sung: Bằng cách này bạn có thể truy cập các thuộc tính với tên đó sẽ là trường hợp không sử dụng được

$x = new StdClass;

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

object(stdClass)#1 (2) { 
    ["a b"]=> 
    int(1) 
    ["x y"]=> 
    int(2) 
}
(không phải là bạn nên, nhưng trong trường hợp bạn phải).
Nếu bạn muốn làm những thứ thậm chí fancier bạn nên xem xét reflection

-7
$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); 

tại sao chỉnh sửa: trước: sử dụng eval (ác) sau: không có eval ở tất cả. đang già trong ngôn ngữ này.

+0

Đây là lời khuyên rất xấu, hàm eval() là một công cụ rất nguy hiểm và sẽ khiến bạn cực kỳ dễ bị tấn công. http://www.blog.highub.com/php/php-core/php-eval-is-evil/ sẽ cung cấp cho bạn một số thông tin. – ridecar2

+2

Đánh giá là gốc của tất cả những điều ác – r4ccoon

+3

Xóa câu trả lời này và bạn sẽ có một huy hiệu! – Thermech

0

Đây là nỗ lực của tôi. Nó có một số kiểm tra 'ngu ngốc' phổ biến được tích hợp sẵn, đảm bảo bạn không cố gắng đặt hoặc nhận một thành viên không có sẵn.

Bạn có thể di chuyển các kiểm tra 'property_exists' đó sang __set và __get tương ứng và gọi chúng trực tiếp trong 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"; 

?> 
3

Đơn giản, $ obj -> {$ obj-> Name} dấu ngoặc nhọn sẽ bao quanh thuộc tính giống như biến số biến.

Đây là tìm kiếm hàng đầu. Nhưng đã không giải quyết được câu hỏi của tôi, mà đã sử dụng $ này. Trong trường hợp hoàn cảnh của tôi bằng cách sử dụng dấu ngoặc nhọn cũng giúp ...

ví dụ với Code Igniter get instance

trong một sourced lớp thư viện được gọi là một cái gì đó với một cá thể của lớp cha mẹ

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

lớp thư viện cần phải nguồn từ một lớp khác cũng có trường hợp cha mẹ

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

Nếu bạn muốn truy cập thuộc tính mà không tạo biến số trung gian, hãy sử dụng ký hiệu {}:

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

Đó cũng cho phép bạn xây dựng các tên thuộc tính trong một vòng lặp ví dụ:

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

Không hoạt động trong php gần đây. –

+6

Đây là cách duy nhất nếu bạn muốn truy cập giá trị mảng '$ this -> {$ property} [$ name]', nếu không '$ this -> $ property [$ name]' sẽ ném một lỗi – goyote

+5

Tôi bằng cách sử dụng PHP 5.4.8 và nó đang hoạt động. – b01

0

gì chức năng này không có gì nó sẽ kiểm tra nếu tài sản tồn tại trên lớp này của bất cứ đứa trẻ của mình, và nếu như vậy nó nhận được giá trị nếu không nó sẽ trả về null. Vì vậy, bây giờ các thuộc tính là tùy chọn và động.

/** 
* 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; 
} 

Cách sử dụng:

const CONFIG_FILE_PATH_PROPERTY = 'configFilePath'; 

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

Có thể có câu trả lời cho câu hỏi này, nhưng bạn có thể muốn xem các cuộc di cư đến PHP 7

backward incompatible change

nguồn: php.net

0

Trong trường hợp bất cứ ai khác muốn tìm một tài sản sâu o không biết chiều sâu, tôi đã đưa ra dưới đây mà không cần phải lặp qua tất cả các thuộc tính được biết đến của tất cả trẻ em. Ví dụ: để tìm $ Foo-> Bar-> baz hoặc $ Foo-> baz, hoặc $ Foo-> Bar-> Baz-> dave, trong đó $ path là một chuỗi như '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}; 

} 

Và sau đó gọi với một cái gì đó như:

$propertyString = getXMLAttribute('string'); // '@Foo/Bar/baz' 
$propertyString = substr($propertyString, 1); 
$moduleCaller = new ModuleCaller(); 
echo $moduleCaller->callModule($propertyString); 
Các vấn đề liên quan