Làm cách nào để có được một thuộc tính trong PHP dựa trên chuỗi? Tôi sẽ gọi nó magic
. Vậy là magic
gì?
$obj->Name = 'something';
$get = $obj->Name;
sẽ giống như ...
magic($obj, 'Name', 'something');
$get = magic($obj, 'Name');
Làm cách nào để có được một thuộc tính trong PHP dựa trên chuỗi? Tôi sẽ gọi nó magic
. Vậy là magic
gì?
$obj->Name = 'something';
$get = $obj->Name;
sẽ giống như ...
magic($obj, 'Name', 'something');
$get = magic($obj, 'Name');
Câu trả lời:
Như thế này
<?php
$prop = 'Name';
echo $obj->$prop;
Hoặc, nếu bạn có quyền kiểm soát lớp, hãy triển khai giao diện ArrayAccess và chỉ cần làm điều này
echo $obj['Name'];
ArrayAccess
, Countable
và một trong những giao diện iterator, nó chủ yếu là không thể phân biệt từ một bình thườngarray()
Nếu bạn muốn truy cập thuộc tính mà không tạo biến trung gian, hãy sử dụng {}
ký hiệu:
$something = $object->{'something'};
Điều đó cũng cho phép bạn xây dựng tên thuộc tính trong một vòng lặp chẳng hạn:
for ($i = 0; $i < 5; $i++) {
$something = $object->{'something' . $i};
// ...
}
$this->{$property}[$name]
, nếu không $this->$property[$name]
sẽ gây ra lỗi
$this->$property[$name]
thực sự có thể thành công, mặc dù đây có thể là một lỗi. $name
được âm thầm đúc thành một số nguyên. Trong trường hợp của một chuỗi không phải là số 0
. Sau đó, chỉ số chuỗi này của giá trị $property
được sử dụng làm tên thuộc tính. Nếu $property
giữ giá trị "abc", thì điều này sẽ đề cập đến thuộc tính $this->a
(chỉ số 0). Nếu có một tài sản như vậy thì điều này sẽ thành công.
Những gì bạn đang hỏi về được gọi là Biến biến . 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à truy cập 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
Một cái gì đó như thế này? Không thử nghiệm nó nhưng sẽ hoạt động tốt.
function magic($obj, $var, $value = NULL)
{
if($value == NULL)
{
return $obj->$var;
}
else
{
$obj->$var = $value;
}
}
Chỉ cần lưu trữ 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;
Có thể có câu trả lời cho câu hỏi này, nhưng bạn có thể muốn xem những chuyển đổi này sang PHP 7
nguồn: php.net
Thật đơn giản, $ obj -> {$ obj-> Name}, dấu ngoặc nhọn sẽ bao bọc thuộc tính giống như một biến số.
Đây là một tìm kiếm hàng đầu. Nhưng không giải quyết được câu hỏi của tôi, đó là sử dụng $ this. Trong trường hợp hoàn cảnh của tôi, sử dụng dấu ngoặc nhọn cũng giúp ...
ví dụ với Code Igniter lấy ví dụ
trong một lớp thư viện có nguồn gốc gọi là một cái gì đó với một thể hiện của lớp cha
$this->someClass='something';
$this->someID=34;
lớp thư viện cần lấy nguồn từ lớp khác cũng với thể hiện cha mẹ
echo $this->CI->{$this->someClass}->{$this->someID};
Cũ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 có tên không thể sử dụng được
$ x = StdClass mới;$ prop = 'a b'; $ x -> $ prop = 1; $ x -> {'x y'} = 2; var_dump ($ x);
đối tượng (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).
Trong trường hợp bất kỳ ai khác muốn tìm một tài sản sâu không rõ độ sâu, tôi đã đưa ra cách dưới đây mà không cần phải lặp qua tất cả các thuộc tính đã biết 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);
Đâ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 thiết lập hoặc có được 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' đó thành __set và __get tương ứng và gọi chúng trực tiếp trong ma thuật ().
<?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";
?>
Hàm này làm gì là nó kiểm tra xem thuộc tính có tồn tại trên lớp này của bất kỳ đứa con nào không và nếu có thì nó sẽ 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à năng độ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;
}
Sử dụng:
const CONFIG_FILE_PATH_PROPERTY = 'configFilePath';
$configFilePath = $this->getIfExist(self::CONFIG_FILE_PATH_PROPERTY);
$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);
why chỉnh sửa: trước: sử dụng eval (ác) sau: không có eval nào cả. đã cũ trong ngôn ngữ này.