ฉันจะได้รับคุณสมบัติใน PHP ตามสตริงได้อย่างไร magic
ฉันจะเรียกมันว่า แล้วอะไรmagic
ล่ะ?
$obj->Name = 'something';
$get = $obj->Name;
จะเป็นเช่น ...
magic($obj, 'Name', 'something');
$get = magic($obj, 'Name');
ฉันจะได้รับคุณสมบัติใน PHP ตามสตริงได้อย่างไร magic
ฉันจะเรียกมันว่า แล้วอะไรmagic
ล่ะ?
$obj->Name = 'something';
$get = $obj->Name;
จะเป็นเช่น ...
magic($obj, 'Name', 'something');
$get = magic($obj, 'Name');
คำตอบ:
แบบนี้
<?php
$prop = 'Name';
echo $obj->$prop;
หรือถ้าคุณมีการควบคุมคลาสให้ใช้อินเทอร์เฟซArrayAccessและทำสิ่งนี้
echo $obj['Name'];
ArrayAccess
, Countable
และเป็นหนึ่งในอินเตอร์เฟซ iterator มันเป็นส่วนใหญ่แตกต่างจากปกติarray()
หากคุณต้องการเข้าถึงคุณสมบัติโดยไม่ต้องสร้างตัวแปรกลางให้ใช้{}
สัญกรณ์:
$something = $object->{'something'};
ที่ช่วยให้คุณสร้างชื่อคุณสมบัติในลูปตัวอย่างเช่น:
for ($i = 0; $i < 5; $i++) {
$something = $object->{'something' . $i};
// ...
}
$this->{$property}[$name]
มิฉะนั้น$this->$property[$name]
จะเกิดข้อผิดพลาด
$this->$property[$name]
อาจประสบความสำเร็จจริง ๆ แม้ว่านี่จะเป็นข้อผิดพลาด $name
ถูกส่งไปยังจำนวนเต็มแบบไม่มีการโต้ตอบ 0
ในกรณีของสตริงที่ไม่ใช่ตัวเลขนี้เป็น จากนั้นสตริงดัชนีนี้ของค่าที่$property
ใช้เป็นชื่อคุณสมบัติ หาก$property
เก็บค่า "abc" สิ่งนี้จะอ้างถึงคุณสมบัติ$this->a
(ดัชนี 0) หากมีคุณสมบัติเช่นนี้ก็จะประสบความสำเร็จ
สิ่งที่คุณกำลังถามถึงจะเรียกว่าตัวแปรตัวแปร สิ่งที่คุณต้องทำคือเก็บสตริงของคุณไว้ในตัวแปรและเข้าถึงได้โดย:
$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
อะไรแบบนี้? ยังไม่ได้ทดสอบ แต่ควรใช้งานได้ดี
function magic($obj, $var, $value = NULL)
{
if($value == NULL)
{
return $obj->$var;
}
else
{
$obj->$var = $value;
}
}
เพียงแค่เก็บชื่อคุณสมบัติในตัวแปรและใช้ตัวแปรเพื่อเข้าถึงคุณสมบัติ แบบนี้:
$name = 'Name';
$obj->$name = 'something';
$get = $obj->$name;
อาจมีคำตอบสำหรับคำถามนี้ แต่คุณอาจต้องการดูการย้ายข้อมูลไปยัง PHP 7
แหล่งที่มา: php.net
มันง่าย $ obj -> {$ obj-> ชื่อ} วงเล็บปีกกาจะล้อมรอบคุณสมบัติเหมือนกับตัวแปรตัวแปร
นี่เป็นการค้นหายอดนิยม แต่ไม่ได้แก้ไขคำถามของฉันซึ่งใช้ $ นี่ ในกรณีของฉันที่ใช้ตัวยึดแบบโค้งก็ช่วยได้ ...
ตัวอย่างกับ Code Igniter รับอินสแตนซ์
ในคลาสไลบรารีที่มาเรียกสิ่งที่มีอินสแตนซ์คลาสหลัก
$this->someClass='something';
$this->someID=34;
คลาสไลบรารีที่ต้องการแหล่งที่มาจากคลาสอื่นพร้อมกับอินสแตนซ์ของผู้ปกครอง
echo $this->CI->{$this->someClass}->{$this->someID};
เช่นเดียวกับการเพิ่ม: วิธีนี้คุณสามารถเข้าถึงคุณสมบัติที่มีชื่อที่ไม่สามารถใช้งานได้
$ x = 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) }(ไม่ใช่ว่าคุณควร แต่ในกรณีที่คุณต้อง)
ในกรณีที่คนอื่นต้องการหาสมบัติลึกที่ไม่รู้จักฉันได้มาด้านล่างโดยไม่จำเป็นต้องวนซ้ำผ่านคุณสมบัติที่รู้จักทั้งหมดของเด็กทุกคน
ตัวอย่างเช่นการค้นหา $ 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);
นี่คือความพยายามของฉัน มันมีการตรวจสอบทั่วไป 'โง่เขลา' อยู่ภายในทำให้แน่ใจว่าคุณไม่ได้พยายามตั้งค่าหรือรับสมาชิกที่ไม่มีอยู่
คุณสามารถย้ายการตรวจสอบ '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";
?>
ฟังก์ชั่นนี้ทำหน้าที่ตรวจสอบว่ามีทรัพย์สินอยู่ในชั้นเรียนของลูกของเขาหรือไม่และถ้าเป็นเช่นนั้นมันจะได้รับค่ามิฉะนั้นจะคืนค่าว่าง ดังนั้นตอนนี้คุณสมบัติเป็นทางเลือกและแบบไดนามิก
/**
* 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);
$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);
ทำไมแก้ไข: ก่อน: ใช้ eval (ชั่วร้าย) หลัง: ไม่มีหลักฐานเลย แก่ตัวในภาษานี้