2009-12-10 40 views

Trả lời

48

Bạn có thể nhận được chúng với reflection API

Tôi giả sử bạn muốn để có được tên của hằng số dựa trên giá trị của biến của bạn (giá trị của giá trị == biến đổi). Nhận tất cả các hằng số được định nghĩa trong lớp, lặp lại chúng và so sánh các giá trị của các hằng số đó với giá trị của biến của bạn. Lưu ý rằng với phương pháp này bạn có thể nhận được một số hằng số khác mà bạn muốn, nếu có hai hằng số có cùng giá trị.

dụ:

class Foo { 
    const ERR_SOME_CONST = 6001; 
    const ERR_SOME_OTHER_CONST = 5001; 

    function bar() { 
     $x = 6001; 
     $fooClass = new ReflectionClass ('Foo'); 
     $constants = $fooClass->getConstants(); 

     $constName = null; 
     foreach ($constants as $name => $value) 
     { 
      if ($value == $x) 
      { 
       $constName = $name; 
       break; 
      } 
     } 

     echo $constName; 
    } 
} 

ps: làm bạn nhớ nói lý do tại sao bạn cần điều này, vì nó có vẻ rất không bình thường ...

+1

Không có gì nghiêm trọng, trên thực tế. Chỉ cần suy nghĩ về cách để vượt qua mã lỗi từ hàm lớp. Đối với tôi const ERR_SOME_ERROR = 'ERR_SOME_ERROR' có vẻ kỳ lạ, tôi nghĩ rằng hàm getLastError() của tôi có thể trả về một cái gì đó như mảng (5003 => 'ERR_SOME_ERROR', 5002 => 'ERR_SOME_ERR2') và vân vân. Chỉ cần có mã lỗi và tên lỗi được trả về. Vâng, tôi càng nghĩ về nó, tôi có thể sẽ không sử dụng nó (cho cú pháp khác thường như bạn đã nói) :) –

+0

cũng cần nó cho CURLE_ * hỗ trợ liên tục, nơi 'curl_multi_strerror' không có sẵn –

+2

Tôi" cần "một cái gì đó như thế này để cung cấp đầu ra lỗi đẹp hơn mà không phải viết lại cách chúng tôi theo dõi một số mã lỗi nhất định được lưu trữ dưới dạng hằng số. – Frug

12

Với Reflection:

$class = new ReflectionClass("Foo"); 
$constants = $class->getConstants(); 

$constants là một mảng chứa tất cả các tên và giá trị của các hằng số được định nghĩa trong lớp Foo.

1

Tất cả các hằng số có thể được gán cho một mảng bằng cách sử dụng hàm này.

$const = get_defined_constants(); 

sau đó sử dụng chức năng sau đây bạn có thể in các cấu trúc mảng

echo "<pre>"; 

print_r($const); 

và bạn có thể xem giải thích thêm ở đây www.sugunan.com

20

Đây là những gì tôi đã làm để đạt được nó. Lấy cảm hứng từ Jan Hancic.

class ErrorCode 
{ 
    const COMMENT_NEWCOMMENT_DISABLED = -4; 
    const COMMENT_TIMEBETWEENPOST_ERROR = -3; 
    /** 
    * Get error message of a value. It's actually the constant's name 
    * @param integer $value 
    * 
    * @return string 
    */ 
    public static function getErrorMessage($value) 
    { 
     $class = new ReflectionClass(__CLASS__); 
     $constants = array_flip($class->getConstants()); 

     return $constants[$value]; 
    } 
} 
+3

Chỉ muốn nói rằng điều này sẽ không hoạt động nếu các hằng số có cùng giá trị. Không phải là một vấn đề hầu hết thời gian, nhưng yea ... – Populus

7

Tôi biết đây là một câu hỏi cũ và tất cả, nhưng tôi vẫn cảm thấy rằng tôi có một số đầu vào hữu ích. Tôi thực hiện điều này bằng cách sử dụng một lớp trừu tượng mà tất cả các enums của tôi mở rộng. Lớp trừu tượng chứa một phương thức toString() chung;

abstract class BaseEnum{ 
    private final function __construct(){ } 

    public static function toString($val){ 
     $tmp = new ReflectionClass(get_called_class()); 
     $a = $tmp->getConstants(); 
     $b = array_flip($a); 

     return ucfirst(strtolower($b[$val])); 
    } 
} 

//actual enum 
final class UserType extends BaseEnum { 
    const ADMIN = 10; 
    const USER = 5; 
    const VIEWER = 0; 
} 

Bằng cách này bạn có thể nhận được chuỗi người có thể đọc được để sử dụng ở đầu ra, trên mọi môi trường mở rộng cơ sở. Hơn nữa, việc bạn triển khai enum, là final, không thể được gia hạn và bởi vì hàm tạo trong BaseEnumprivate nó không bao giờ có thể được khởi tạo.

Vì vậy, ví dụ, nếu bạn thấy một danh sách tất cả tên người dùng với các loại của họ, bạn có thể làm điều gì đó như

foreach($users as $user){ 
    echo "<li>{$user->name}, ".UserType::toString($user->usertype)."</li>"; 
} 
2

nếu bạn cần để có được những giá trị không đổi trên một phương pháp của lớp tương tự, bạn chỉ cần để sử dụng toán tử tự. Bạn có thể sử dụng phản chiếu nếu bạn muốn sử dụng các hằng số trên một lớp khác

class Foo { 
    const ERR_SOME_CONST = 6001; 

    function bar() { 
     self::ERR_SOME_CONST; 
    } 
} 
3

Cảnh báo: Bằng cách này bạn không nên lập trình ...(Nếu bạn đang không chắc chắn những gì bạn đang làm :))

tôi đã viết 1 hàng mà Echos hằng số và các giá trị số của mình bằng cách lựa chọn của bạn CATEGORY_

vì vậy đây là danh sách các CATEGORY_ ERR_

foreach(get_defined_constants() as $key => $value) if(strlen($key)>5) if(substr($key, 0,5)=="ERR_") echo"<br>Found an php ERR_ constant! : ".$key."=>".$value; 

Và nếu bạn muốn chỉ là một bạn đang tìm kiếm theo số => tôi tạo ra 1row chức năng:

//input parameters: CATEGORYNAME_ , #constantNumber 
function getConstantName($category,$constantNumber){foreach(get_defined_constants() as $key => $value) if(strlen($key)>strlen($category)) if(substr($key, 0,strlen($category))==$category) if($value==$constantNumber) return $key; return "No constant found.";} 

vì vậy, ví dụ som thông tin điện tử thường xuyên với số lượng 64:

echo "NameOfConstant: ".getConstantName("INFO_",64); 

sẽ ra cái gì đó như: NameOfConstant: INFO_LICENSE

5

Tất cả các câu trả lời khác bao gồm những điểm cần thiết. Nhưng, nếu điên một lớp lót của bạn là gì, sau đó:

function getConstantName($class, $value) 
{ 
    return array_flip((new \ReflectionClass($class))->getConstants())[$value]; 
} 

Nếu bạn cần để xử lý các trường hợp giá trị có thể không thực sự là một trong những hằng số, sau đó bạn có thể bỏ thêm một dòng:

function getConstantName($class, $value) 
{ 
    $map = array_flip((new \ReflectionClass($class))->getConstants()); 
    return (array_key_exists($value, $map) ? $map[$value] : null); 
} 
+1

Đây là giải pháp dễ dàng và nhanh chóng. Lật mảng và kiểm tra khóa. –

2

OK, OK, tôi biết mọi thứ đã được đề cập :) Nhưng Jan Hančič đã yêu cầu sử dụng, vì vậy tôi sẽ chia sẻ của tôi. Ngoài ra: mọi người dường như sử dụng array_flip(). Tại sao không array_search()?

Tôi cần nó trong một lớp mở rộng \ Exception và là lớp cơ sở của một tập hợp nhỏ các ngoại lệ cụ thể của tôi. Mỗi lớp ngoại lệ cụ thể này bao gồm một miền ngoại lệ rộng và đã xác định một số nguyên nhân ngoại lệ chính xác. Lý do? Tôi không muốn có một số ngoại lệ để duy trì và ghi nhớ. Ngoài ra, có bộ xử lý ngoại lệ mà đổ ruột của ngoại lệ vào tệp nhật ký - và ở đây tôi cần lấy tên không đổi như cố gắng giải mã ngoại lệ gây ra từ trạng thái khá đau đớn.

Ví dụ từ kịch bản CLI của tôi:

class AbstractException extends Exception { 
    public function getName() { 
     return array_search($this->getCode(), (new ReflectionClass($this))->getConstants()); 
    } 
} 

class SyntaxException extends AbstractException { 
    const BAD_SYNTAX = 90; 
    const REQUIRED_PARAM = 91; 
    const REQUIRED_VALUE = 92; 
    const VALUE_TYPE = 93; 
    const VALUE_OUT_OF_BOUNDS = 94; 

    public function __construct ($message = "", $code = self::BAD_SYNTAX, Exception $previous = NULL) { 
     $script = basename($GLOBALS['argv'][0]); 

     echo "Invalid syntax: $message \nSee: `$script --help` for more information\n"; 
     parent::__construct($message, $code, $previous); 
    } 
} 

// in autoload include 
set_exception_handler(function(Exception $e) { 
    error_log(basename($GLOBALS['argv'][0]) . ';'. date('Y-m-d H:i:s') .';'. $e->getName() .';'. $e->getMessage() .';'. $e->getFile() .';'. $e->getLine() ."\n", 3, 'error.log'); 
    exit ($e->getCode()); 
}); 
Các vấn đề liên quan