2010-03-31 44 views
17

Tôi muốn tự động tạo đối tượng PHP và tham số sẽ là tùy chọn.Tham số truyền PHP khi tạo đối tượng mới, call_user_func_array cho đối tượng

Ví dụ, thay vì làm điều này:

$test = new Obj($param); 

Tôi muốn làm điều gì đó như thế này (tạo ob mới là hư cấu):

$test = create_new_obj('Obj', $param); 

Có chức năng như vậy trong php? Một cái gì đó tương tự như call_user_func_array, nhưng đối với đối tượng thay thế.

+0

để làm rõ thêm một chút, tên lớp là biến (thay đổi) và $ param phụ thuộc vào lớp được tải. Đôi khi không có thông số. Về cơ bản nó tải động từ nhiều lớp khác nhau tùy theo tình huống. – Patrick

+0

Tôi nghĩ câu trả lời của tôi dưới đây vẫn phù hợp với hóa đơn từ những gì bạn mô tả (tên lớp biến, tham số xây dựng tùy chọn). Không có lý do gì bạn không thể chuyển một giá trị '$ param' vào một hàm khởi tạo cho một lớp không cần nó. Nếu, mặt khác, bạn đang nói rằng loại đối tượng được tạo ra thực sự * phụ thuộc vào '$ param' *, thì bạn sẽ muốn xem xét một thứ gì đó giống như Mẫu Nhà máy: http: //en.wikipedia .org/wiki/Factory_method_pattern. PHP không thể xử lý các quyết định xây dựng của bạn cho bạn trong trường hợp đó ... bạn sẽ cần viết logic để quyết định những gì được xây dựng. – zombat

Trả lời

5

Bạn có thể tự động tạo ra một đối tượng miễn là bạn biết tên lớp:

$objName = 'myClass'; 
$test = new $objName($param); 

Bạn có thể dễ dàng xác định một hàm __construct() lấy default arguments cũng như nếu đó là một yêu cầu của logic xây dựng của bạn.

[Chỉnh sửa ghi chú]: Đây là một khái niệm được gọi là variable variables và có một số ví dụ trong hướng dẫn nơi lệnh new được giới thiệu.

16

Vì một số nhà thầu có thể lấy số lượng đối số thay đổi, nên sử dụng phương pháp sau để phù hợp với nó.

$r = new ReflectionClass($strClassName); 
$myInstance = $r->newInstanceArgs($arrayOfConstructorArgs); 

Ví dụ, nếu constructor Car bạn mất 3 args

$carObj = new Car($color, $engine, $wheels); 

Sau đó

$strClassName = 'Car'; 
$arrayOfConstructorArgs = array($color, $engine, $wheels); 
$r = new ReflectionClass($strClassName); 
$carObj = $r->newInstanceArgs($arrayOfConstructorArgs); 

http://php.net/manual/en/class.reflectionclass.php
http://php.net/manual/en/reflectionclass.newinstanceargs.php

+0

Phản ánh là tốn kém. Bạn nên sử dụng 'func_get_args()' cho việc này. – zombat

+4

Trong thử nghiệm của tôi bằng cách sử dụng phản ánh trong php không phải là chậm hơn so với func \ _get \ _args(). Ngoài ra, bạn không phải thay đổi mã của các lớp. – VolkerK

7

Trong trường hợp này tôi sử dụng nhà máy-phương pháp. họ có thể dễ dàng được định nghĩa trong lớp trừu tượng:

class Foobar { 

    public function __construct($foo, $bar) 
    { 
     // do something 
    } 

    static public function factory($foo, $bar) 
    { 
     return new self($foo, $bar); 
    } 
} 

với điều này bạn có thể sử dụng call_user_func_array():

$my_foobar_obj = call_user_func_array('Foobar::factory', array($foo, $bar)); 
0

Dựa trên câu trả lời @ Chris (https://stackoverflow.com/a/2550465/1806628), đây là một cách sử dụng của các tầng lớp phản ánh:

abstract class A{ 
    // the constructor writes out the given parameters 
    public function __construct(){ 
     var_dump(func_get_args()); 
    } 

    public function copy(){ 
     // find our current class' name, __CLASS__ would return A 
     $thisClass = get_class($this); 
     $tmp = new ReflectionClass($thisClass); 
     // pass all the parameters recieved to the new object 
     $copy = $tmp->newInstanceArgs(func_get_args()); 

     return $copy; 
    } 
} 

class B extends A{} 

// create a new B object, with no parameters 
$b = new B(); 

// create another b, but with other parameters 
$c = $b->copy('the parameter of the copied B'); 

Điều này rất hữu ích, nếu bạn muốn tạo hàm sao chép đối tượng trong lớp tổ tiên và không biết, liệu lớp con có cần tham số trong tương lai hay không.

4

Đây là một phiên bản sạch những gì bạn muốn:

class ClassName { 
    public static function init(){  
     return (new ReflectionClass(get_called_class()))->newInstanceArgs(func_get_args());   
    } 

    public static function initArray($array=[]){  
     return (new ReflectionClass(get_called_class()))->newInstanceArgs($array);   
    } 

    public function __construct($arg1, $arg2, $arg3){ 
     ///construction code 
    } 
} 

Bình thường phương pháp xấu xí của việc tạo ra một trường hợp đối tượng mới sử dụng mới

$obj = new ClassName('arg1', 'arg2', 'arg3'); 
echo $obj->method1()->method2(); 

gọi tĩnh nhờ sủ dụng init thay vì mới

echo ClassName::init('arg1', 'arg2', 'arg3')->method1()->method2(); 

gọi tĩnh sử dụng initArray thay vì mới

echo ClassName::initArray(['arg1', 'arg2', 'arg3'])->method1()->method2(); 
20

Tính đến PHP 5.6, bây giờ bạn có thể đạt được điều này với một dòng mã bằng công Argument mới điều hành Tháo bao bì (...).

Đây là một ví dụ đơn giản.

$className='Foo'; 
$args=['arg1','arg2','arg3']; 

$newClassInstance=new $className(...$args); 

Xem PHP Variable-length argument lists để biết thêm thông tin.

+0

không cần nhiều hơn 1 dòng trong 5,5- hoặc sau đó. '$ db = (new ReflectionClass ('Foo')) -> newInstanceArgs ($ args);' – hanshenrik

Các vấn đề liên quan