PHP学习笔记5:常量

PHP学习笔记5:常量

image-20211129162010327

图源:php.net

语法

php常量的基本用途与其它语言类似,即在编译期而非运行期提供一种确定的、不会改变的值:

const PROGRAM_VERSION = '1.0.0';
const DB_VERSION = '1.0.0';
const AUTHOR = 'icexmoon';

这些常量通常用于定义软件版本号、作者信息等。

按习惯,常量名通常以全大写字母结合_定义。

在Go语言是个例外,其变量和常量命名都不推荐使用_,所以常量命名只能是大小写字母的驼峰样式。

常量与超全局变量类似,一经定义,可以在任何地方使用:

function use_const(){
    echo "the program version is :".PROGRAM_VERSION.PHP_EOL;
    echo "the author is :".AUTHOR.PHP_EOL;
}
use_const();
// the program version is :1.0.0
// the author is :icexmoon

一般来说,常量必须被定义为基础类型的数值,或者在编译期可以评估结果的表达式(比如简单的数学运算):

const COUNT = 1 + 2 + 3;
const ARR = array(1, 2, 3);
const MSG = implode(',', array(1, 2, 3));
// Fatal error: Constant expression contains invalid operations in ...

但php提供一种特别的方式,可以“在运行时定义常量”:

define('MSG', implode(',', array(1, 2, 3)));
echo MSG.PHP_EOL;
// 1,2,3

使用一个没有定义的常量将产生错误:

<?php
echo MY_CONST.PHP_EOL;
// Fatal error: Uncaught Error: Undefined constant "MY_CONST" in ...

在php8.0以前,使用一个未定义的常量,可能会被解析为常量名称组成的字符串,并产生一个E_NOTICE级别的错误,在php8.0之后,会产生E_ERROR

可以使用defined检查常量是否被定义:

if (defined('MSG')){
    echo "MSG is defined".PHP_EOL;
    // MSG is defined
}

可以通过constant()函数传入包含常量名称的字符串来获取常量值:

<?php
$constName = 'MSG';
const MSG = 'hello';
echo constant($constName).PHP_EOL;
// hello

这在不知道常量名称,只有包含常量名称的变量时很有用。

使用get_defined_constants可以获取当前已定义的所有常量:

<?php
$consts = get_defined_constants();
foreach ($consts as $constName => $constValue){
    if (strpos($constName, 'E_')===0){
        echo "name:{$constName} value:{$constValue}".PHP_EOL;
    }
}
// name:E_ERROR value:1
// name:E_RECOVERABLE_ERROR value:4096
// name:E_WARNING value:2
// name:E_PARSE value:4
// name:E_NOTICE value:8
// name:E_STRICT value:2048
// ...

常量也可以定义在类中,这里以一个自定义异常类作为说明:

<?php
class UserException extends Exception
{
    const ERROR_DB = 0;
    const ERROR_OTHER = 1;
    const ERROR_WEB = 2;
    const ERROR_INPUT = 3;
    private $errFlag;
    private $msg;
    private $exp;
    public function __construct(?Exception $exp, string $msg, int $errFlag)
    {
        $this->errFlag = $errFlag;
        $this->msg = $msg;
        $this->exp = $exp;
    }
    public function getErrFlag(): int
    {
        return $this->errFlag;
    }
    public function getMsg(): string
    {
        return $this->msg;
    }
}
try {
    throw new UserException(null, "测试代码", UserException::ERROR_OTHER);
} catch (UserException $e) {
    if ($e->getErrFlag() == UserException::ERROR_OTHER) {
        echo "other error, reason is " . $e->getMsg() . PHP_EOL;
        // other error, reason is 测试代码
    }
}

这使用类常量来定义自定义异常类的错误类别,这在以前是一种相当常见的方式,当然从php8.1开始,可以使用枚举来取代。

此外,从php7.1.0开始,类常量可以使用访问修饰符了:

class UserException extends Exception
{
    public const ERROR_DB = 0;
    public const ERROR_OTHER = 1;
    private const ERROR_WEB = 2;
    protected const ERROR_INPUT = 3;
    ...

不过在我看来似乎作用不大,一般来说类常量是无需进行封装和保护的。

还需要注意的是,const只能在最外部的作用域或类定义中使用:

<?php
function define_const(){
    const MSG = "hello";
    // Parse error: syntax error, unexpected token "const" ...
}

当然,define()并没有这种限制:

function define_const(){
    define("MSG","hello");
}
if (defined("MSG")){
    echo MSG.PHP_EOL;
}
define_const();
if (defined("MSG")){
    echo MSG.PHP_EOL;
    // hello
}

预定义常量

php的预定义常量的来源很多,包括php内核、扩展等等,可能因为加载的模块不同而不同,这里展示一些常见的预定义常量:

<?php
function print_var($var)
{
    echo $var . PHP_EOL;
}
print_var(PHP_VERSION); //PHP版本
// 8.1.0
print_var(PHP_OS); //当前操作系统
// WINNT
print_var(PHP_OS_FAMILY); //操作系统家族
// Windows
print_var(PHP_INT_MAX); //当前硬件平台支持的最大整形
// 9223372036854775807
print_var(PHP_BINARY); //php的二进制执行文件路径
// D:\software\Coding\php-8.1.0-nts-Win32-vs16-x64\php.exe

更多的预定义常量可以查看官方手册预定义常量

魔术常量

“魔术常量”其实并不是真正的常量,它们会随着执行代码的不同而不同,通常会保存当前代码的运行相关的环境信息,合理地使用魔术常量可以避免代码中出现不必要的“硬编码”:

include "d:/workspace/http/php-notes/ch5/const.php";
echo PROGRAM_VERSION.PHP_EOL;
echo AUTHOR.PHP_EOL;
// 1.0.0
// icexmoon

上面的代码有很明显的硬编码,这会使得当前应用的部署路径限定死了,只要部署的路径不对,代码就无法运行,甚至根本无法在Linux主机上部署代码,因为Linux压根不会有d:/...这样的目录。

更合理的方式是使用魔术变量:

include __DIR__."/const.php";

当然这只是用于演示魔术变量的用途,实际上可以使用更灵活的写法:

include "./const.php";

对于一个完善的Web应用,往往会采用在配置文件中定义APP_ROOT常量,其余地方都会使用include APP_ROOT.'/XXX.php'的方式来处理引用路径。这样做的好处在于所有项目部署需要修改的信息都集中在一个配置文件中,减少了部署代码的工作量。

魔术常量都以前后双下划线的方式命名,类似于__XXX__。常用的魔术变量有:

  • __DIR__,表示当前代码所在的目录路径。
  • __FILE__,表示当前代码文件的路径。

完整的魔术常量列表见官方手册魔术常量

以上就是常量的相关内容,虽然这部分有点少,但我依然决定尽量以PHP手册的章节来组织笔记结构。

谢谢阅读。

往期内容

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值