常數名稱可以是空字串。
程式碼
define("", "foo");
echo constant("");
輸出
foo
(PHP 4 >= 4.0.4, PHP 5, PHP 7, PHP 8)
constant — 傳回常數的值
傳回 name
指定的常數值。
如果您需要取得常數的值,但不知道它的名稱(例如,它儲存在變數中或由函式返回),constant() 函式就很有用。
name
常數名稱。
返回常數的值。
範例 #1 使用 constant() 搭配常數
<?php
define("MAXSIZE", 100);
echo MAXSIZE;
echo constant("MAXSIZE"); // 與前一行相同
interface bar {
const test = 'foobar!';
}
class foo {
const test = 'foobar!';
}
$const = 'test';
var_dump(constant('bar::'. $const)); // string(7) "foobar!"
var_dump(constant('foo::'. $const)); // string(7) "foobar!"
?>
範例 #2 使用 constant() 搭配列舉案例 (PHP 8.1.0 起)
<?php
enum Suit
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
$case = 'Hearts';
var_dump(constant('Suit::'. $case)); // enum(Suit::Hearts)
?>
如果您要參考類別常數(無論是否使用命名空間,因為總有一天您可能會開始使用它們),這樣做最不容易出錯
<?php
class Foo {
const BAR = 42;
}
?>
<?php
namespace Baz;
use \Foo as F;
echo constant(F::class.'::BAR');
?>
因為 F::class 會被解參考為您正在使用的任何命名空間捷徑(而且這些捷徑比在字串字面值中使用寫死的命名空間更容易使用 IDE 重構)
值得注意的是,關鍵字 'self' 可用於從定義它的類別內部擷取常數
<?php
class Foo {
const PARAM_BAR = 'baz';
public function getConst($name) {
return constant("self::{$name}");
}
}
$foo = new Foo();
echo $foo->getConst('PARAM_BAR'); // 顯示 'baz'
?>
從 PHP 5.4.6 開始,constant() 不會注意在使用它的檔案中可能定義的任何命名空間別名。也就是說,constant() 的行為始終如同從全域命名空間呼叫一樣。這表示以下程式碼將無法運作
<?php
class Foo {
const BAR = 42;
}
?>
<?php
namespace Baz;
use \Foo as F;
echo constant('F::BAR');
?>
但是,呼叫 constant('Foo::BAR') 將會如預期般運作。
嚴格來說,您可以定義名稱對變數無效的常數
<?php
// $3some 不是有效的變數名稱
// 這將無法運作
$3some = 'invalid';
// 這樣可以
define('3some', 'valid');
echo constant('3some');
?>
當然,這不是一個好的做法,但 PHP 可以讓你這樣做。
或許這會派上用場
$file_ext 是圖片的副檔名
<?php
if ( imagetypes() & @constant('IMG_' . strtoupper($file_ext)) )
{
$file_ext = $file_ext == 'jpg' ? 'jpeg' : $file_ext;
$create_func = 'ImageCreateFrom' . $file_ext;
}
?>
當你經常寫像這樣的程式碼時
<?php
if(defined('FOO') && constant('FOO') === 'bar')
{
...
}
?>
為了避免錯誤,你可以使用以下函式來取得常數的值。
<?php
function getconst($const)
{
return (defined($const)) ? constant($const) : null;
}
?>
最後你可以用以下方式檢查值
<?php
if(getconst('FOO') === 'bar')
{
...
}
?>
這樣寫更簡潔。
檢查常數是否為空是有問題的…
你不能這樣做
<?php
define('A', '');
define('B', 'B');
if (empty(B)) // 語法錯誤
if (empty(constant('B'))) // 致命錯誤
// 所以,感謝 LawnGnome 在 IRC 上的提示,你可以將常數轉換為布林值(空字串為 false)
if (((boolean) A) && ((boolean) B))
// 執行程式碼
?>
<?php
namespace Foo;
define(__NAMESPACE__ . '\Bar', 'its work'); // ..但 IDE 可能會發出提示
echo Bar; // its work
要存取類別常數的值,請使用以下技巧。
<?php
class a {
const b = 'c';
}
echo constant('a::b');
// 輸出:c
?>
回覆 VGR_experts_exchange at edainworks dot com
要檢查常數是否為布林值,請改用以下方法
<?php
if (TRACE === true) {}
?>
比使用 defined() 和 constant() 檢查簡單的布林值快得多且更簡潔。
在我看來,使用 ($var === true) 或 ($var === false) 而不是 ($var) 或 (!$var) 是檢查布林值的最佳方法,無論是什麼情況。不會造成歧義。
從物件回傳常數。您可以使用正規表達式過濾或依值比對,從值中找到常數名稱。
有時非常有用。
<?php
function findConstantsFromObject($object, $filter = null, $find_value = null)
{
$reflect = new ReflectionClass($object);
$constants = $reflect->getConstants();
foreach ($constants as $name => $value)
{
if (!is_null($filter) && !preg_match($filter, $name))
{
unset($constants[$name]);
continue;
}
if (!is_null($find_value) && $value != $find_value)
{
unset($constants[$name]);
continue;
}
}
return $constants;
}
?>
範例
<?php
類別 Example
{
const GENDER_UNKNOW = 0;
const GENDER_FEMALE = 1;
const GENDER_MALE = 2;
const USER_OFFLINE = false;
const USER_ONLINE = true;
}
$all = findConstantsFromObject('Example');
$genders = findConstantsFromObject('Example', '/^GENDER_/');
$my_gender = 1;
$gender_name = findConstantsFromObject('Example', '/^GENDER_/', $my_gender);
if (isset($gender_name[0]))
{
$gender_name = str_replace('GENDER_', '', key($gender_name));
}
else
{
$gender_name = 'WTF!';
}
?>
使用 constant()(或其他方法)來確保 your_constant 已被定義,這一點尤其重要,當它被定義為 `true` 或 `false` 時。
例如,取自這個 Stackoverflow 問題
https://stackoverflow.com/questions/5427886/php-undefined-constant-testing/56604602#56604602)
如果 `BOO` 因故未被定義為常數,
<?php if(BOO) do_something(); ?>
會被評估為 `TRUE` 並繼續執行。這是一個相當出乎意料的結果。
原因是當 PHP 在其已定義常數列表中沒有看到 `BOO` 時,它會假設您「忘記」在 `BOO` 周圍加上引號。
所以它會評估:`if ('BOO')`...
由於除了空字串以外的每個字串都是「真值」,因此該表達式會被評估為 `true`,並且 do_something() 會意外執行。
如果您改用
<?php if (constant(BOO)) do_something() ?>
那麼如果未定義 `BOO`,`constant(BOO)` 會被評估為 `null`,
它是「假值」,而 `if (null)`... 會變成 `false`,因此 do_something() 會如預期般被跳過。
當特定常數被定義為例外情況,「假值」為預設值,而具有「真值」會暴露安全漏洞時,PHP 關於未定義常數的行為尤其明顯。例如,
<?php if (IS_SPECIAL_CASE) show_php_info() ?>。
還有其他方法可以解決 PHP 的這種行為,例如
<?php if (BOO === true) do_something(); ?>
或者
<?php if (defined('BOO') && BOO) do_something() ?>。
請注意,只有使用 `defined()` 的版本才能正常運作,而不會拋出 PHP 警告「錯誤訊息」。
這裡有一個 php repl.it 示範
https://repl.it/@sherylhohman/php-undefined-constants-beware-of-truthy-conversion?language=php_cli&folderId=
(說明:我也提交了一個答案到上面連結的 SO 問題)
您可以在設定檔中使用已定義常數的名稱來定義值,例如:
在您的 php 程式碼中
define("MY_CONST",999);
在您的設定檔中
my = MY_CONST
讀取檔案時,執行以下操作
$my = constant($value); // 其中 $value 是字串 "MY_CONST"
現在 $my 的值為 999
這個函式在呼叫類別常數時會區分命名空間。
使用
<?php namespace sub;
class foo {
const BAR = 'Hello World';
}
constant('foo::BAR'); // 錯誤
constant('sub\foo::BAR'); // 可以運作
?>
這似乎不會影響使用 'define' 函式定義的常數。這些常數最終都會被定義在根命名空間中,除非在常數的字串名稱中隱式定義了另一個命名空間。
// 1) 您可以將常數的名稱儲存在預設變數中
// 並且在不識別其名稱的情況下使用它 :)
$str= "constName";
define("constName","this is constant");
echo constant($str);
輸出
this is constant
// 2) 適合動態產生常數
function generateConst( $const , $value , $sensitivity=TRUE )
{
define( "$const" , "$value ",$sensitivity);
}
$CONST="cost";
$VALUE="100$";
generateConst( $CONST , $VALUE);
echo constant($const);
輸出
100$