ยกตัวอย่างคลาสจากตัวแปรใน PHP หรือไม่?


146

ฉันรู้ว่าคำถามนี้ฟังดูค่อนข้างคลุมเครือดังนั้นฉันจะทำให้ชัดเจนขึ้นด้วยตัวอย่าง:

$var = 'bar';
$bar = new {$var}Class('var for __construct()'); //$bar = new barClass('var for __construct()');

นี่คือสิ่งที่ฉันต้องการจะทำ คุณจะทำอย่างไร ฉันสามารถใช้ eval () ได้เช่นนี้:

$var = 'bar';
eval('$bar = new '.$var.'Class(\'var for __construct()\');');

แต่ฉันอยากอยู่ให้ห่างจาก eval () มีวิธีการทำเช่นนี้โดยไม่ต้อง eval ()?

คำตอบ:


214

ใส่ classname ลงในตัวแปรก่อน:

$classname=$var.'Class';

$bar=new $classname("xyz");

นี่คือสิ่งที่คุณจะเห็นในรูปแบบของโรงงาน

ดูNamespaces และคุณสมบัติภาษาแบบไดนามิกสำหรับรายละเอียดเพิ่มเติม


2
นี่คือวิธีที่ฉันทำ โปรดทราบว่าจากภายในคลาสคุณสามารถใช้พาเรนต์และตัวเองได้
Ross

1
ในบันทึกที่คล้ายกันคุณสามารถทำ $ var = 'ชื่อ'; $ obj -> { 'ได้รับ' $ var.} ();
มาริโอ

1
จุดดี แต่ที่ใช้งานได้เฉพาะวิธีการโทรและไม่ก่อสร้าง
พอลดิกซัน

12
หากคุณทำงานกับ namespace ให้ใส่ namespace ปัจจุบันลงในสตริง:$var = __NAMESPACE__ . '\\' . $var . 'Class';
bastey

@bastey - แต่ทำไม ฉันใช้เวลามากเกินไปในการหาว่าทำไมสิ่งนี้ถึงใช้งานไม่ได้หากไม่มีเนมสเปซหน้าชื่อคลาส ...
jkulak

72

ถ้าคุณใช้เนมสเปซ

ในการค้นพบของฉันฉันคิดว่าเป็นเรื่องดีที่จะพูดถึงว่าคุณ (เท่าที่ฉันจะบอกได้) ต้องประกาศเส้นทางเนมสเปซเต็มรูปแบบของชั้นเรียน

MyClass.php

namespace com\company\lib;
class MyClass {
}

index.php

namespace com\company\lib;

//Works fine
$i = new MyClass();

$cname = 'MyClass';

//Errors
//$i = new $cname;

//Works fine
$cname = "com\\company\\lib\\".$cname;
$i = new $cname;

6
ทางออกเดียวที่ทำงานเมื่อต้องการสร้างด้วยเนมสเปซเป็นของคุณ ขอบคุณสำหรับการแบ่งปัน!
Tiago Gouvêa

แต่นี่เป็นเพียงแปลกทำไมมันจะไม่ใช้เนมสเปซที่ประกาศ?
Yisrael Dov

@YisraelDov ใช่มันเป็นเคาน์เตอร์ที่ใช้งานง่ายแน่นอน แต่ด้วยเหตุผลใดก็ตามที่มันทำตัวแปลก ๆ ในบริบทนี้ ขอบคุณ php
csga5000

@YisraelDov ฉันเดาว่าเป็นเพราะในกรณีนั้นการยกคลาสจากเนมสเปซอื่นจะทำให้ปวดหัวมาก พิจารณาว่าตัวแปรสามารถส่งผ่านได้ เมื่อ classname ถูกเขียนเป็นข้อความลงในไฟล์ php ใครก็ตามที่เขียนมันจะรู้ว่า namespace มันถูกเขียนอะไร แต่เมื่อตัวแปรถูกส่งผ่านระหว่างฟังก์ชั่นมันจะเป็นฝันร้ายที่จะติดตามมัน นอกจากนี้ถ้าคุณใช้ get_class () มันจะคืนค่าชื่อคลาส FQ เพื่อให้สามารถเก็บไว้ในตัวแปรได้ทันทีและใช้งานได้ทุกที่ ถ้ามันขึ้นอยู่กับเนมสเปซของไฟล์มันจะทำงานได้ไม่ดีนัก
sbnc.eu

61

วิธีส่งพารามิเตอร์ตัวสร้างแบบไดนามิกเช่นกัน

หากคุณต้องการส่งผ่านพารามิเตอร์ตัวสร้างแบบไดนามิกไปยังคลาสคุณสามารถใช้รหัสนี้:

$reflectionClass = new ReflectionClass($className);

$module = $reflectionClass->newInstanceArgs($arrayOfConstructorParameters);

ข้อมูลเพิ่มเติมเกี่ยวกับคลาสและพารามิเตอร์แบบไดนามิก

PHP> = 5.6

ในฐานะของ PHP 5.6 คุณสามารถทำให้สิ่งนี้ง่ายยิ่งขึ้นด้วยการใช้Argument Unpacking :

// The "..." is part of the language and indicates an argument array to unpack.
$module = new $className(...$arrayOfConstructorParameters);

ขอบคุณ DisgruntledGoat ที่ชี้ให้เห็นว่า


7
จาก PHP 5.6 คุณควรใช้การเปิดกล่องโต้แย้ง:new $className(...$params)
DisgruntledGoat

29
class Test {
    public function yo() {
        return 'yoes';
    }
}

$var = 'Test';

$obj = new $var();
echo $obj->yo(); //yoes

ไม่ไม่ใช่ตัวอย่างที่ดี ใช้ได้เฉพาะในกรณีที่ทุกอย่างอยู่ในไฟล์ php เดียวกัน
ฟัลโบ

2
2ndGAB ควรลบความคิดเห็นนี้ การโหลดอัตโนมัติไม่มีอะไรเกี่ยวข้องกับคำถามนี้
Jim Maguire

-1

ฉันจะแนะนำวิธีการcall_user_func()หรือcall_user_func_arrayphp คุณสามารถตรวจสอบพวกเขาได้ที่นี่ ( call_user_func_array , call_user_func )

ตัวอย่าง

class Foo {
static public function test() {
    print "Hello world!\n";
}
}

 call_user_func('Foo::test');//FOO is the class, test is the method both separated by ::
 //or
 call_user_func(array('Foo', 'test'));//alternatively you can pass the class and method as an array

หากคุณมีข้อโต้แย้งที่คุณส่งผ่านไปยังวิธีการใช้call_user_func_array()ฟังก์ชั่น

ตัวอย่าง.

class foo {
function bar($arg, $arg2) {
    echo __METHOD__, " got $arg and $arg2\n";
}
}

// Call the $foo->bar() method with 2 arguments
call_user_func_array(array("foo", "bar"), array("three", "four"));
//or
//FOO is the class, bar is the method both separated by ::
call_user_func_array("foo::bar"), array("three", "four"));

3
คำตอบนี้ใช้ไม่ได้กับคำถาม OP ขอให้วิธี INSTANTIATE คลาส (เรียกใช้เมธอด __ โครงสร้างแบบไดนามิก) จากสตริงตัวแปรและรับ CLASS OBJECT กลับมาเป็นตัวแปรใหม่ - คำแนะนำของคุณจะคืนค่า VALUE ของเมธอด class-> ([]) กำลังโทรหาไม่ใช่คลาสอ็อบเจ็กต์ดังนั้นจึงไม่ใช้กับกรณีนี้ ดูค่าที่ส่งคืนphp.net/manual/en/function.call-user-func-array.php
ChrisN
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.