Nhận giá trị của hằng số lớp được chọn động trong PHP


114

Tôi muốn có thể làm điều gì đó như sau:

class ThingIDs
{
    const Something = 1;
    const AnotherThing = 2;
}

$thing = 'Something';
$id = ThingIDs::$thing;

Điều này không hiệu quả. Có một cách đơn giản để làm một cái gì đó tương đương? Lưu ý rằng tôi bị mắc kẹt với lớp học; nó nằm trong thư viện mà tôi không thể viết lại. Tôi đang viết mã lấy đối số trên dòng lệnh và tôi thực sự muốn nó lấy tên tượng trưng thay vì số id.


Bạn có thể thử ThingIDs::{$thing}?
David Rodrigues

Đã thử. Cho tôi lỗi phân tích cú pháp thay vì lỗi thời gian chạy nghiêm trọng.
Ben

Câu trả lời:


182

$id = constant("ThingIDs::$thing");

http://php.net/manual/en/ Chức năng.constant.php


1
Mặt lưu ý: nếu bạn muốn kiểm tra đầu tiên hay không hằng số được xác định, đó làdefined("ThingIDs::$thing");
Parris Varney

3
hoặc $ id = hằng ("self :: $ thing");
Dòng

3
Tương tự như thế này,$id = constant(sprintf('%s::%s', ThingIDs::class, $thing));
David Baucum,

4
@DavidBaucum tại sao bạn lại muốn làm phức tạp quá mức này? Yêu cầu này khá đơn giản và không liên quan đến đầu vào bên ngoài, người dùng có thể thao tác. Bên cạnh đó, bạn đang gọi một hàm khác bởi vì, tôi đoán, bạn không thích chuỗi được nối với các dấu phân cách?
ReSpawN

5
Tùy thuộc vào trường hợp sử dụng của bạn, giải pháp của tôi ít phức tạp hơn. Cụ thể là nếu bạn đang sử dụng tính năng tự động tải PSR-4, thì mã của bạn có thể trở nên tồi tệ khi FQDN được đánh vần ở mọi nơi. Bằng cách sử dụng useở đầu tệp và sau đó sử dụng ::classphương pháp để có được FQDN một cách kỳ diệu, cải thiện khả năng đọc.
David Baucum

27

Sử dụng phản chiếu

$r = new ReflectionClass('ThingIDs');
$id = $r->getConstant($thing);

3
Reflections thực sự cung cấp rất nhiều cái nhìn sâu sắc về các lớp, phương thức và hơn thế nữa và có vẻ như rất nhiều người ngại thực hiện bước đó để hiểu chúng. Câu trả lời chính xác.
Mike Mackintosh

2
@mikemackintosh Tôi đã thực hiện các bước để hiểu chúng, nhưng chưa thấy nhiều về tác động hiệu suất so với câu trả lời được chấp nhận. ĐÓ là điều mà tôi muốn biết. Việc khởi tạo một lớp mới có vẻ như nó sẽ có hiệu suất lớn hơn là chỉ gọi một hằng số tĩnh. suy nghĩ của bạn về điều đó là gì?
dudewad

13

Nếu bạn đang sử dụng không gian tên, bạn nên bao gồm không gian tên với lớp.

echo constant('My\Application\ThingClass::ThingConstant'); 

3
<?php

class Dude {
    const TEST = 'howdy';
}

function symbol_to_value($symbol, $class){
    $refl = new ReflectionClass($class);
    $enum = $refl->getConstants();
    return isset($enum[$symbol])?$enum[$symbol]:false;
}

// print 'howdy'
echo symbol_to_value('TEST', 'Dude');

3

Chức năng trợ giúp

Bạn có thể sử dụng một chức năng như sau:

function class_constant($class, $constant)
{
    if ( ! is_string($class)) {
        $class = get_class($class);
    }

    return constant($class . '::' . $constant);
}

Nó có hai đối số:

  • Tên lớp hoặc cá thể đối tượng
  • Tên hằng số của lớp

Nếu một cá thể đối tượng được truyền, tên lớp của nó sẽ được suy ra. Nếu bạn sử dụng PHP 7, bạn có thể sử dụng ::classđể chuyển tên lớp thích hợp mà không cần phải suy nghĩ về không gian tên.

Ví dụ

class MyClass
{
    const MY_CONSTANT = 'value';
}

class_constant('MyClass', 'MY_CONSTANT'); # 'value'
class_constant(MyClass::class, 'MY_CONSTANT'); # 'value' (PHP 7 only)

$myInstance = new MyClass;
class_constant($myInstance, 'MY_CONSTANT'); # 'value'

0

Nếu bạn có một tham chiếu đến chính lớp đó thì bạn có thể làm như sau:

if (defined(get_class($course). '::COURSES_PER_INSTANCE')) {
   // class constant is defined
}

0

Vấn đề của tôi tương tự với chủ đề này. Khi bạn có đối tượng, nhưng không có tên lớp, bạn có thể sử dụng:

$class_name = get_class($class_object);
$class_const = 'My_Constant';

$constant_value = constant($class_name.'::'.$class_const);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.