2010-05-12 38 views
20

Tôi đang cố tạo một đối tượng PHP (5) có thể lặp qua các thuộc tính của nó, xây dựng truy vấn SQL chỉ dựa trên các thuộc tính công khai của nó chứ không phải các thuộc tính riêng.Phát hiện nếu thuộc tính đối tượng là riêng tư trong PHP

Vì phương thức đối tượng gốc này được sử dụng bởi các đối tượng con, tôi không thể đơn giản chọn bỏ qua các thuộc tính riêng theo tên (tôi sẽ không biết chúng nằm trong đối tượng con).

Có cách nào đơn giản để phát hiện từ bên trong đối tượng thuộc tính của nó là riêng tư không?

Dưới đây là một ví dụ đơn giản về những gì tôi đã có cho đến nay, nhưng sản lượng này bao gồm giá trị của $ bar:

class testClass { 

    public $foo = 'foo'; 
    public $fee = 'fee'; 
    public $fum = 'fum'; 

    private $bar = 'bar'; 

    function makeString() 
    { 
     $string = ""; 

     foreach($this as $field => $val) { 

      $string.= " property '".$field."' = '".$val."' <br/>"; 

     } 

     return $string; 
    } 

} 

$test = new testClass(); 
echo $test->makeString(); 

Cung cấp đầu ra:

property 'foo' = 'foo' 
property 'fee' = 'fee' 
property 'fum' = 'fum' 
property 'bar' = 'bar' 

Tôi muốn nó không bao gồm 'bar'.

Nếu có cách tốt hơn để lặp qua chỉ các thuộc tính công khai của một đối tượng, điều đó cũng sẽ hoạt động ở đây.

Trả lời

9

Bạn có thể sử dụng Reflection để kiểm tra các thuộc tính của lớp học. Để chỉ nhận các thuộc tính công khai và được bảo vệ, hãy đặt cấu hình bộ lọc phù hợp theo phương thức ReflectionClass::getProperties.

Dưới đây là ví dụ nhanh về phương pháp makeString của bạn bằng cách sử dụng phương pháp này.

public function makeString() 
{ 
    $string = ""; 
    $reflection = new ReflectionObject($this); 
    $properties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC); 
    foreach ($properties as $property) { 
     $name = $property->getName(); 
     $value = $property->getValue($this); 
     $string .= sprintf(" property '%s' = '%s' <br/>", $name, $value); 
    } 
    return $string; 
} 
+0

Cảm ơn - Tôi nghĩ powtac đã đánh bại bạn trong khoảng 30 giây, nhưng có, hoạt động chính xác khi cần. – Hippyjim

+0

Vâng, tôi đoán đã dành quá nhiều thời gian để tạo ra một câu trả lời khá hay với các liên kết gọn gàng và gọn gàng với tài liệu. Bài học kinh nghiệm, câu trả lời nhanh và bẩn từ đây trở đi! :-) – salathe

1
foreach (get_class_vars(get_class($this)) .... 
+0

Ngoài ra còn có lớp phản chiếu và phương pháp ma thuật __get() – powtac

+0

Bạn nói đúng, nó trả về các vars của phạm vi hiện tại -> $ này có nghĩa là tất cả ... – powtac

+0

Tôi sợ tôi không biết gì về lớp phản chiếu - Tôi sẽ cần phải làm một số Googling nặng. Cảm ơn con trỏ. – Hippyjim

1

Bạn có thể sử dụng mảng để lưu trữ các thuộc tính công khai, thêm một số phương thức trình bao bọc và sử dụng mảng để chèn dữ liệu vào SQL.

18

Kiểm tra mã này từ http://php.net/manual/reflectionclass.getproperties.php#93984

public function listProperties() { 
    $reflect = new ReflectionObject($this); 
    foreach ($reflect->getProperties(ReflectionProperty::IS_PUBLIC /* + ReflectionProperty::IS_PROTECTED*/) as $prop) { 
     print $prop->getName() . "\n"; 
    } 
    } 
+2

Đó chính xác là những gì tôi cần. Cảm ơn bài học! – Hippyjim

2

Nếu bạn cast đối tượng đến một mảng trước khi lặp lại trên nó, các thành viên private và protected sẽ có tiền tố đặc biệt:

class Test{ 
    public $a = 1; 
    private $b = 1; 
    protected $c = 1; 
} 
$a = new Test(); 
var_dump((array) $a); 

màn hình này:

array(3) { 
    ["a"]=> 
    int(1) 
    ["Testb"]=> 
    int(1) 
    ["*c"]=> 
    int(1) 
} 

Cũng có các ký tự ẩn, không được hiển thị. Nhưng bạn có thể viết mã để phát hiện chúng. Ví dụ: biểu thức chính quy /\0\*\0(.*)$/ sẽ khớp với các khóa được bảo vệ và /\0.*\0(.*)$/ sẽ khớp với các khóa riêng tư. Trong cả hai, nhóm chụp đầu tiên khớp với tên thành viên.

4

Một giải pháp nhanh hơn mà tôi tìm thấy:

class Extras 
{ 
    public static function get_vars($obj) 
    { 
     return get_object_vars($obj); 
    } 
} 

và sau đó gọi bên trong TestClass của bạn:

$vars = Extras::get_vars($this); 

additional reading in PHP.net

0

Bạn có thể sử dụng Reflection API để kiểm tra khả năng hiển thị thuộc tính:

$rp = new \ReflectionProperty($object,$property); 
if($rp->isPrivate) { 
    // Run if the property is private 
} else { 
    // Run if the property is Public or Protected 
} 
Các vấn đề liên quan