2009-08-14 30 views
43

Tôi có điều này:Bắt thuộc tính tĩnh từ một lớp học với tên lớp năng động trong PHP

  • một chuỗi biến mà giữ tên lớp ($classname)
  • một chuỗi biến với giữ tên thuộc tính ($propertyname)

Tôi muốn nhận được thuộc tính đó từ lớp đó, vấn đề là, thuộc tính tĩnh và tôi không biết cách thực hiện điều đó.

Nếu tài sản không phải là tĩnh, nó đã có:

$classname->$propertyname; 

nếu tài sản được một phương pháp, tôi có thể đã sử dụng call_user_function

call_user_func(array($classname, $propertyname)); 

Nhưng trong trường hợp của tôi, tôi vừa mất. Tuy nhiên tôi hy vọng rằng điều đó là có thể. Với hàng nghìn chức năng mà PHP có, anh ta cũng có cái gì đó tốt hơn cho điều này. Có lẽ tôi đang thiếu một cái gì đó?

Cảm ơn!

Edit:

  • cho những người có eval() giải pháp: cảm ơn, nhưng nó là ra câu hỏi
  • cho những người có get _class _vars() giải pháp: cảm ơn, nhưng có vẻ như nó sẽ trả về "các thuộc tính mặc định của cho lớp " (php.net), và có, tôi muốn giá trị đó có thể thay đổi được (mặc dù nó có thể giúp tôi trong một số trường hợp)

Trả lời

66

Nếu bạn đang sử dụng PHP 5.3.0 hoặc cao hơn, bạn có thể sử dụng như sau:

$classname::$$propertyname; 

Thật không may, nếu bạn đang sử dụng một phiên bản thấp hơn 5.3.0, bạn đang bị mắc kẹt sử dụng eval() ( get_class_vars() sẽ không hoạt động nếu giá trị động).

$value = eval($classname.'::$'.$propertyname.';'); 


EDIT: Tôi vừa mới nói get_class_vars() sẽ không hoạt động nếu giá trị là năng động, nhưng dường như, các thành viên tĩnh biến là một phần của "các thuộc tính mặc định của một lớp học ".Bạn có thể sử dụng các wrapper sau:

function get_user_prop($className, $property) { 
    if(!class_exists($className)) return null; 
    if(!property_exists($className, $property)) return null; 

    $vars = get_class_vars($className); 
    return $vars[$property]; 
} 

class Foo { static $bar = 'Fizz'; } 

echo get_user_prop('Foo', 'bar'); // echoes Fizz 
Foo::$bar = 'Buzz'; 
echo get_user_prop('Foo', 'bar'); // echoes Buzz 

Thật không may, nếu bạn muốn thiết lập các giá trị của biến, bạn vẫn sẽ cần phải sử dụng eval(), nhưng với một số xác nhận tại chỗ, đó là không quá ác.

function set_user_prop($className, $property,$value) { 
    if(!class_exists($className)) return false; 
    if(!property_exists($className, $property)) return false; 

    /* Since I cannot trust the value of $value 
    * I am putting it in single quotes (I don't 
    * want its value to be evaled. Now it will 
    * just be parsed as a variable reference). 
    */ 
    eval($className.'::$'.$property.'=$value;'); 
    return true; 
} 

class Foo { static $bar = 'Fizz'; } 

echo get_user_prop('Foo', 'bar'); // echoes Fizz 
set_user_prop('Foo', 'bar', 'Buzz'); 
echo get_user_prop('Foo', 'bar'); // echoes Buzz 

set_user_prop() với xác nhận này nên được an toàn. Nếu mọi người bắt đầu đặt những thứ ngẫu nhiên là $className$property, nó sẽ thoát khỏi chức năng vì nó sẽ không phải là một lớp hoặc tài sản hiện có. Kể từ $value, nó không bao giờ thực sự được phân tích cú pháp dưới dạng mã để bất cứ điều gì chúng đặt vào đó sẽ không ảnh hưởng đến tập lệnh.

+0

+1 cho chức năng bao bọc. – nilamo

+0

Ôi trời ơi, tôi vừa định hỏi "nhưng làm thế nào để thiết lập ...". Dude, bạn hoàn toàn đá! – treznik

+1

Trong PHP 5 trở lên (Tôi đang ở trên 5.2), bạn có thể sử dụng sự phản chiếu cho điều này, như tôi vừa học được. Xem câu trả lời của tôi ở đây: http://stackoverflow.com/questions/3354628/from-the-string-name-of-a-class-can-i-get-a-static-variable/3364090#3364090 –

0

Bạn sẽ có thể làm điều gì đó ng như:

eval("echo $classname::$propertyname;"); 

Tôi vừa làm một bài kiểm tra nhanh và làm việc này cho tôi. Không chắc chắn nếu có một cách tốt hơn hay không, nhưng tôi đã không thể tìm thấy một.

+1

eval là :) ác không bao giờ sử dụng nó. luôn có lựa chọn thay thế tốt hơn –

0

'eval' trông rất gần với 'điều ác' và tôi ghét sử dụng nó và/hoặc nhìn thấy mã đó. Với một vài ý tưởng từ các câu trả lời khác, đây là một cách để tránh nó ngay cả khi php của bạn không phải là 5.3 hoặc cao hơn.

Đã thay đổi để phản ánh thử nghiệm dựa trên nhận xét.

class A { 
    static $foo = 'bar'; 
} 

A::$foo = 'baz'; 
$a = new A; 

$class = get_class($a); 
$vars = get_class_vars($class); 

echo $vars['foo']; 

Đầu ra 'baz'.

+2

'get_class_vars()' chỉ trả về giá trị ban đầu của '$ foo'. Nếu '$ foo' thay đổi, giá trị bạn nhận được từ' get_class_vars() 'sẽ không thay đổi. –

+0

Trên thực tế, theo định nghĩa nó không phải là công việc, nhưng dường như không. –

+0

Tôi đồng ý với bình luận thứ hai của bạn. Tôi nghĩ rằng đó là một chút kỳ lạ, vì vậy tôi đã thử nghiệm nó và cập nhật câu trả lời của tôi. Điều đó phù hợp với những gì bạn tìm thấy? – nilamo

0

get_class_vars không giống với get_object_vars.

Tôi nghĩ rằng get_clas_vars phải trả về giá trị thuộc tính ban đầu.

1

Một điều tôi nhận thấy là bạn không thể đặt các biến được bảo vệ trong các lớp tĩnh vì lệnh eval() chạy trong phạm vi bên ngoài lớp. Điều duy nhất để giải quyết vấn đề này là thực hiện một phương thức tĩnh bên trong/mọi lớp chạy eval(). Phương thức này có thể được bảo vệ như call_user_func() [để gọi phương thức setter] cũng chạy từ bên trong lớp.

13

Tôi nghĩ rằng đây là đơn giản nhất:

$foo = new ReflectionProperty('myClassName', 'myPropertyName'); 
print $foo->getValue(); 
10

Để trả về một giá trị biến được thiết lập bởi một biến tĩnh bạn cần phải gọi:

$static_value = constant($classname.'::'.$propertyname); 

Kiểm tra các tài liệu hướng dẫn :: PHP Constant Documentation

+0

+1 cho gợi ý. Nhưng tôi nghĩ rằng nó chỉ hoạt động cho các hằng số lớp và không phải lớp biến tĩnh. –

+0

Tôi đã thử nghiệm, nó chỉ làm việc với hằng số lớp, nhưng KHÔNG với các biến tĩnh lớp. –

0

Ngay cả khi bạn đã nói eval không nằm trong câu hỏi, trước PHP 5.3 giải pháp đơn giản nhất vẫn là sử dụng eval:

eval("\$propertyval = $classname::\$propertyname;"); 
echo $propertyval; 
-1

Bắt và thiết lập cả hai thuộc tính tĩnh tĩnh và phi mà không sử dụng Reflection

Sử dụng Reflection công trình nhưng nó là tốn kém

Dưới đây là những gì tôi sử dụng cho mục đích này,

Nó hoạt động cho PHP 5 >= 5.1.0 vì tôi đang sử dụng property_exist

function getObjectProperty($object, $property) 
{ 
    if (property_exists(get_class($object), $property)) { 
     return array_key_exists($property, get_object_vars($object)) 
      ? $object->{$property} 
      : $object::$$property; 
    } 
} 

function setObjectProperty($object, $property, $value) 
{ 
    if (property_exists(get_class($object), $property)) { 
     array_key_exists($property, get_object_vars($object)) 
      ? $object->{$property} = $value 
      : $object::$$property = $value; 
    } 
} 
+0

Nó sẽ không hoạt động với PHP <5.3 vì '$ object :: $$ property' không phải là cú pháp hợp lệ cho nó. –

0

Bạn có thể sử dụng ReflectionClass:

class foo 
{ 
    private static $bar = "something"; 
} 

$class = "foo"; 
$reflector = new ReflectionClass($class); 
$static_vars = $reflector->getStaticProperties(); 
var_dump($static_vars["bar"]); 
Các vấn đề liên quan