在PHP中,静态变量(Static Variables)和常量(Constants)是用来存储不变或特定生命周期内保持状态的值的两种不同手段。
静态变量(Static Variables):
定义:
在PHP中,静态变量在函数内部通过关键字 static
来定义。每次函数被调用时,静态变量并不会被重新初始化,而是保留上次调用时的状态。
function exampleFunction() {
static $count = 0;
$count++;
echo "This is call number: " . $count;
}
exampleFunction(); // 输出 "This is call number: 1"
exampleFunction(); // 输出 "This is call number: 2"
// 每次调用该函数,$count 都会累加,因为它是一个静态变量
特点:
- 静态变量的作用域限于定义它的块或函数,但它在函数退出后仍保留其值。
- 静态变量可以在多次函数调用间维持其状态,即使函数已经结束执行。
常量(Constants):
定义:
在PHP中,常量通过 define()
函数或者 const
关键字在类中定义。常量一旦被定义,其值就不能被改变。
define("PI", 3.14); // 全局常量定义
class MyClass {
const MY_CONSTANT = 'Some value'; // 类常量定义
}
echo PI; // 输出 3.14
echo MyClass::MY_CONSTANT; // 输出 "Some value"
特点:
- 常量名全程大写,单词之间下划线连接,这是一种约定俗成的编码规范。
- 常量在整个脚本的生命周期内保持不变,试图更改常量的值会导致错误。
- 常量的作用域取决于定义的位置,可以是全局的也可以是类内的(类常量只在类的上下文中可用)。
相同点:
- 都用来存储不变的值。
- 都能在程序的不同位置被访问和使用。
区别:
- 常量的值在其定义后不能更改,而静态变量在函数内部可以更改(尽管函数外部不能直接访问)。
- 常量的作用域更广,可以直接在任何地方通过其名称访问,而静态变量则局限于定义它的函数或类方法内部,但可以在该函数/方法内部跨调用保持状态。
- 常量的性能理论上优于静态变量,因为编译时就能确定其值,而静态变量在运行时可能会发生改变。
实际使用例子:
- 静态变量:在需要记录函数调用次数、累计计算结果或其他需要跨函数调用保持状态的情况时使用。
- 常量:在程序中需要用到固定不变的数值、配置项、版本号等情况下使用。例如,数据库连接字符串、API密钥、数学常数等。
在PHP中,define()
和 const
关键字都可以用来定义常量,但它们在使用上有一些重要的区别:
-
作用域:
define()
函数可以在任何地方定义全局常量,包括脚本文件的任何位置以及函数或方法内部(尽管函数内部定义的常量仍然是全局可见的)。const
关键字用于在类内部定义类常量,从PHP 5.3.0开始,也可以在命名空间外部定义全局常量。
-
定义时机:
const
定义的常量在编译阶段就已经确定,因此在类加载时就已经知道它的存在。define()
函数定义的常量在运行时动态创建,这意味着它是在解析到这条语句时被定义的。
-
使用场景:
const
只能用于类内部定义常量,格式如下:class MyClass { const MY_CONST = 'value'; }
define()
可以在任何上下文定义常量,包括全局和条件语句中:define('MY_GLOBAL_CONST', 'value');
-
语法和限制:
const
定义的常量必须是静态的标量值(如整数、字符串、布尔值等),不能是表达式或者包含变量。define()
函数第二个参数可以是任何类型的表达式,并且可选地提供第三个参数来控制常量名是否大小写敏感(默认是大小写敏感)。
-
性能:
const
定义理论上具有微弱的性能优势,因为它们在编译时就已知,但这种差异在实际应用中通常不明显。
综上所述,选择使用 define()
还是 const
取决于具体的应用场景,如果需要在类内部定义常量,应使用 const
,在其他情况下,尤其是需要在非类环境中定义常量时,则应使用 define()
函数。同时要注意PHP版本兼容性问题,根据您的PHP版本决定如何使用 const
来定义全局常量。
实例:
在访问PHP类中的成员属性或方法时,如果属性或者方法被声明成 const(定义常量)或者static(声明静态),就必须使用类名或 self
配合 ::
来访问。否则用实例对象或 $this
配合 ->
来访问。
<?php
class A {
const NAME = 'jack';
static $age = 20;
public $sex = 'male';
public function f() {
echo self::NAME; // 用 self 访问常量成员属性时,不加美元符号
echo self::$age; // 用 self 访问静态成员属性时,加美元符号
echo $this->sex; // 用 $this 伪变量访问成员属性时,不加美元符号
}
public static function f_static() {
echo self::NAME;
echo self::$age;
// 静态方法可以不用实例化就调用,所以不能用 $this 伪变量
// Fatal error: Uncaught Error: Using $this when not in object context
echo $this->$sex;
}
}
echo A::NAME;
echo A::$age;
A::f_static();
$a = new A();
echo $a->f();