PHP 完全指南 / 第 4 章 — 变量与类型
第 4 章 — 变量与类型:标量、复合、特殊类型与类型声明
4.1 变量基础
PHP 变量以 $ 符号开头,变量名区分大小写。
<?php
declare(strict_types=1);
$name = "Alice"; // string
$age = 30; // int
$height = 1.68; // float
$isActive = true; // bool
// 变量命名规则
$userName = "Bob"; // camelCase(推荐)
$_private = "hidden"; // 下划线开头(约定为私有)
$MAX_RETRIES = 3; // 常量风格(通常用 const/define)
// PHP 变量名是动态的
$varName = "greeting";
$$varName = "Hello!"; // 可变变量
echo $greeting; // 输出: Hello!
变量赋值行为
<?php
$a = 1;
$b = $a; // 值拷贝($b = 1)
$b = 2;
echo $a; // 仍然是 1
$c = &$a; // 引用赋值($c 指向 $a 的值)
$c = 3;
echo $a; // 变为 3
4.2 标量类型(Scalar Types)
4.2.1 整型(int)
<?php
$decimal = 42;
$binary = 0b101010; // 二进制
$octal = 052; // 八进制
$hex = 0x2A; // 十六进制
// 整型大小(64 位系统)
echo PHP_INT_SIZE; // 8(字节)
echo PHP_INT_MAX; // 9223372036854775807
echo PHP_INT_MIN; // -9223372036854775808
// 数字分隔符(PHP 7.4+)
$population = 1_400_000_000; // 14 亿
$price = 99_99; // 99.99(表示分)
// 整数溢出自动转为 float
$big = PHP_INT_MAX + 1;
var_dump($big); // float(9.2233720368548E+18)
4.2.2 浮点型(float)
<?php
$pi = 3.14159;
$lightSpeed = 2.998e8; // 科学计数法
$electronMass = 9.109e-31;
// ⚠️ 浮点数精度问题
echo 0.1 + 0.2; // 0.30000000000000004
echo (0.1 + 0.2) == 0.3; // false
// 正确比较浮点数
$epsilon = 1e-10;
$equal = abs((0.1 + 0.2) - 0.3) < $epsilon;
var_dump($equal); // bool(true)
// 高精度计算用 bcmath
echo bcadd('0.1', '0.2', 1); // "0.3"
4.2.3 字符串(string)
<?php
// 单引号 — 不解析变量和转义序列(除 \\ 和 \')
$name = 'World';
echo 'Hello, $name!'; // 输出: Hello, $name!
// 双引号 — 解析变量和转义序列
echo "Hello, $name!"; // 输出: Hello, World!
echo "Sum: " . (3 + 4); // 输出: Sum: 7
// Heredoc(双引号行为)
$html = <<<HTML
<div class="greeting">
<h1>Hello, $name!</h1>
</div>
HTML;
// Nowdoc(单引号行为)
$sql = <<<'SQL'
SELECT * FROM users WHERE name = '$name'
SQL;
4.2.4 布尔型(bool)
<?php
// 以下值被认为是 false
var_dump((bool) ""); // false — 空字符串
var_dump((bool) "0"); // false — 字符串 "0"
var_dump((bool) 0); // false — 零
var_dump((bool) 0.0); // false — 零浮点
var_dump((bool) []); // false — 空数组
var_dump((bool) null); // false — null
var_dump((bool) 0.0); // false
// 其他所有值都是 true
var_dump((bool) -1); // true
var_dump((bool) "false"); // true(非空字符串)
var_dump((bool) []); // false
4.3 复合类型(Compound Types)
4.3.1 数组(array)
<?php
// 索引数组
$fruits = ['apple', 'banana', 'cherry'];
echo $fruits[0]; // apple
// 关联数组
$user = [
'name' => 'Alice',
'age' => 30,
'email'=> 'alice@example.com',
];
echo $user['name']; // Alice
// 多维数组
$matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
echo $matrix[1][2]; // 6
4.3.2 对象(object)
<?php
class User
{
public function __construct(
public string $name,
public int $age,
) {}
}
$user = new User('Alice', 30);
echo $user->name; // Alice
4.3.3 可调用类型(callable)
<?php
$greet = function(string $name): string {
return "Hello, {$name}!";
};
echo $greet('World'); // Hello, World!
// 用作回调
$result = array_map(
fn(int $n) => $n * 2,
[1, 2, 3]
);
// [2, 4, 6]
4.4 特殊类型
4.4.1 null
<?php
$x = null;
unset($x); // 同样为 null
var_dump($x); // NULL
// null 合并运算符
$username = $_GET['user'] ?? 'guest';
$name = $user->name ?? 'Anonymous';
// null 安全运算符(PHP 8.0+)
$country = $user?->address?->country ?? 'Unknown';
4.4.2 Resource
资源类型是 PHP 中持有外部资源引用的特殊类型(PHP 8.0+ 逐步用面向对象替代)。
<?php
// 旧方式(resource)
$file = fopen('/tmp/test.txt', 'w');
var_dump($file); // resource(5) of type (stream)
// 新方式(推荐,SplFileObject)
$file = new SplFileObject('/tmp/test.txt', 'w');
$file->fwrite("Hello\n");
4.5 类型声明(Type Declarations)
4.5.1 函数参数与返回值
<?php
declare(strict_types=1);
function createUser(
string $name,
int $age,
string $email = '',
?string $phone = null, // 可为 null
): array {
return [
'name' => $name,
'age' => $age,
'email' => $email,
'phone' => $phone,
];
}
// 正确调用
$user = createUser('Alice', 30, 'alice@example.com');
// 严格模式下,类型不匹配会抛出 TypeError
// createUser('Alice', 'thirty'); // TypeError!
4.5.2 联合类型(Union Types)— PHP 8.0+
<?php
function format(int|float $value): string
{
return number_format($value, 2);
}
echo format(42); // "42.00"
echo format(3.14); // "3.14"
4.5.3 交叉类型(Intersection Types)— PHP 8.1+
<?php
interface Loggable {}
interface Serializable2 {}
function process(Loggable&Serializable2 $obj): void
{
// $obj 必须同时实现两个接口
}
4.5.4 DNF 类型(Disjunctive Normal Form)— PHP 8.2+
<?php
// (A & B) | C 的形式
function handle((Countable&Iterator)|array $value): void
{
// $value 要么同时实现 Countable 和 Iterator
// 要么是一个数组
}
4.5.5 类型列表汇总
| 类型 | PHP 版本 | 示例 |
|---|---|---|
int | 4+ | int $count |
float | 4+ | float $price |
string | 4+ | string $name |
bool | 4+ | bool $active |
array | 4+ | array $items |
callable | 5.4+ | callable $fn |
self | 5+ | self $instance |
parent | 5+ | parent $obj |
object | 7.2+ | object $entity |
iterable | 7.1+ | iterable $list |
void | 7.1+ | 返回类型 |
never | 8.1+ | 返回类型 |
null | 7+(单独) | ?string $name |
mixed | 8.0+ | mixed $value |
static | 8.0+ | 返回类型 |
true / false | 8.2+ | true $flag |
| 联合类型 | 8.0+ | int|string $id |
| 交叉类型 | 8.1+ | A&B $obj |
| DNF | 8.2+ | (A&B)|C $v |
4.6 类型转换(Type Casting)
<?php
// 显式转换
$intVal = (int) "42"; // 42
$floatVal = (float) "3.14"; // 3.14
$stringVal = (string) 42; // "42"
$boolVal = (bool) 1; // true
$arrayVal = (array) "hello"; // ["hello"]
$nullVal = (unset) "value"; // null(已废弃,用 = null 替代)
// 安全转换
$val = intval("42"); // 42
$val = floatval("3.14"); // 3.14
$val = strval(42); // "42"
$val = boolval(1); // true
// filter_var
$int = filter_var("42", FILTER_VALIDATE_INT); // 42 或 false
$email = filter_var("a@b.com", FILTER_VALIDATE_EMAIL); // "a@b.com" 或 false
4.7 常量(Constants)
<?php
// define() 函数(运行时常量)
define('API_VERSION', 'v2');
define('MAX_LOGIN_ATTEMPTS', 5);
define('IS_DEBUG', true);
// const 关键字(编译时常量,推荐)
const APP_NAME = 'MyApp';
const DB_CONFIG = [
'host' => 'localhost',
'port' => 3306,
];
// 类常量
class Config
{
public const VERSION = '1.0.0';
private const MAX_RETRIES = 3;
// 类型化常量(PHP 8.3+)
public const string ENV = 'production';
public const int TIMEOUT = 30;
}
echo Config::VERSION; // 1.0.0
// 接口常量
interface Status
{
const ACTIVE = 1;
const INACTIVE = 0;
const DELETED = -1;
}
// 枚举常量(PHP 8.1+)
enum Color: string
{
case Red = '#FF0000';
case Green = '#00FF00';
case Blue = '#0000FF';
}
4.8 readonly 属性(PHP 8.1+)
<?php
class User
{
public function __construct(
public readonly string $name,
public readonly int $age,
) {}
}
$user = new User('Alice', 30);
echo $user->name; // Alice
// $user->name = 'Bob'; // Error: Cannot modify readonly property
// Readonly 类(PHP 8.2+)
readonly class Point
{
public function __construct(
public float $x,
public float $y,
) {}
}
4.9 业务场景:用户输入验证
<?php
declare(strict_types=1);
class UserInput
{
public function __construct(
public readonly string $name,
public readonly string $email,
public readonly int $age,
) {}
public static function fromArray(array $data): self
{
$name = trim((string) ($data['name'] ?? ''));
if ($name === '') {
throw new InvalidArgumentException('Name is required');
}
if (mb_strlen($name) > 100) {
throw new InvalidArgumentException('Name too long');
}
$email = trim((string) ($data['email'] ?? ''));
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException('Invalid email');
}
$age = (int) ($data['age'] ?? 0);
if ($age < 0 || $age > 150) {
throw new InvalidArgumentException('Invalid age');
}
return new self($name, $email, $age);
}
}
// 使用示例
try {
$user = UserInput::fromArray($_POST);
echo "注册成功: {$user->name}";
} catch (InvalidArgumentException $e) {
echo "验证失败: {$e->getMessage()}";
}
4.10 扩展阅读
上一章:第 3 章 — Hello World 下一章:第 5 章 — 运算符