IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> PHP学习笔记5:常量 -> 正文阅读

[PHP知识库]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手册的章节来组织笔记结构。

谢谢阅读。

往期内容

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-12-05 11:51:19  更:2021-12-05 11:51:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 21:08:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计