2009-12-18 14 views
19

Làm cách nào để tạo một lớp với một mảng đối số đã cho được gửi tới hàm tạo? Nội dung nào đó dọc theo dòng:Có một call_user_func() tương đương để tạo một cá thể lớp mới không?

class a { 
    var $args = false; 
    function a() {$this->args = func_get_args();} 
} 

$a = call_user_func_array('new a',array(1,2,3)); 
print_r($a->args); 

Lý tưởng nhất là cần làm việc, mà không sửa đổi lớp, trong cả PHP4 và PHP5. Bất kỳ ý tưởng?

+2

Tại sao bạn muốn thực hiện như thế này? Bạn đang cố giải quyết vấn đề gì? – Skilldrick

+0

@ Skilldrick: trong trường hợp của tôi, cố gắng triển khai một thùng chứa phụ thuộc đơn giản. –

+0

Có thể trùng lặp của [Cách gọi hàm tạo với lệnh \ _user \ _func \ _array trong PHP] (http://stackoverflow.com/questions/2409237/how-to-call-the-constructor-with-call-user- func-array-in-php) – Maks3w

Trả lời

24

ReflectionClass:newInstance() (hoặc newInstanceArgs()) hãy để bạn làm điều đó.

ví dụ:

class Foo { 
    public function __construct() { 
    $p = func_get_args(); 
    echo 'Foo::__construct(', join(',', $p), ') invoked'; 
    } 
} 

$rc = new ReflectionClass('Foo'); 
$foo = $rc->newInstanceArgs(array(1,2,3,4,5)); 

chỉnh sửa: không ReflectionClass và có lẽ PHP4 tương thích (xin lỗi, không có php4 trong tầm tay ngay bây giờ)

class Foo { 
    public function __construct() { 
    $p = func_get_args(); 
    echo 'Foo::__construct(', join(',', $p), ') invoked'; 
    } 
} 

$class = 'Foo'; 
$rc = new $class(1,2,3,4); 

tốc độ so sánh: Kể từ khi tốc độ phản xạ đã được đề cập ở đây là một chút (tổng hợp) kiểm tra

define('ITERATIONS', 100000); 

class Foo { 
    protected $something; 
    public function __construct() { 
    $p = func_get_args(); 
    $this->something = 'Foo::__construct('.join(',', $p).')'; 
    } 
} 

$rcStatic=new ReflectionClass('Foo'); 
$fns = array(
    'direct new'=>function() { $obj = new Foo(1,2,3,4); }, 
    'indirect new'=>function() { $class='Foo'; $obj = new $class(1,2,3,4); }, 
    'reflection'=>function() { $rc=new ReflectionClass('Foo'); $obj = $rc->newInstanceArgs(array(1,2,3,4)); }, 
    'reflection cached'=>function() use ($rcStatic) { $obj = $rcStatic->newInstanceArgs(array(1,2,3,4)); }, 
); 


sleep(1); 
foreach($fns as $name=>$f) { 
    $start = microtime(true); 
    for($i=0; $i<ITERATIONS; $i++) { 
    $f(); 
    } 
    $end = microtime(true); 
    echo $name, ': ', $end-$start, "\n"; 
    sleep(1); 
} 

mà in trên (không quá nhanh) của tôi máy tính xách tay

direct new: 0.71329689025879 
indirect new: 0.75944685935974 
reflection: 1.3510940074921 
reflection cached: 1.0181720256805 

Điều đó có tệ không?

+0

Hãy nhớ rằng câu trả lời của VolkerK chỉ có sẵn trong PHP5 – Mark

+0

Phản ánh chỉ được hỗ trợ trong PHP5, nhưng đây là cách tôi sẽ làm. –

+0

Tôi khuyên bạn nên sử dụng bất kỳ sự phản ánh nào trong mã sản xuất. Nó rất chậm. –

9

Có một cái nhìn tại Factory Method pattern và kiểm tra this example

Từ Wikipedia:

Nhà máy Phương pháp mô hình là một mẫu thiết kế hướng đối tượng. Giống như các mẫu sáng tạo khác, giao dịch với sự cố khi tạo đối tượng (sản phẩm) mà không chỉ định loại đối tượng chính xác sẽ được tạo .

Nếu bạn không muốn sử dụng một Nhà máy chuyên dụng cho việc này, bạn vẫn có thể wrap Volker's code thành một hàm, ví dụ:

/** 
* Creates a new object instance 
* 
* This method creates a new object instance from from the passed $className 
* and $arguments. The second param $arguments is optional. 
* 
* @param String $className class to instantiate 
* @param Array $arguments arguments required by $className's constructor 
* @return Mixed instance of $className 
*/ 
function createInstance($className, array $arguments = array()) 
{ 
    if(class_exists($className)) { 
     return call_user_func_array(array(
      new ReflectionClass($className), 'newInstance'), 
      $arguments); 
    } 
    return false; 
}