强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

第 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'=> '[email protected]',
];
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, '[email protected]');

// 严格模式下,类型不匹配会抛出 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 版本示例
int4+int $count
float4+float $price
string4+string $name
bool4+bool $active
array4+array $items
callable5.4+callable $fn
self5+self $instance
parent5+parent $obj
object7.2+object $entity
iterable7.1+iterable $list
void7.1+返回类型
never8.1+返回类型
null7+(单独)?string $name
mixed8.0+mixed $value
static8.0+返回类型
true / false8.2+true $flag
联合类型8.0+int|string $id
交叉类型8.1+A&B $obj
DNF8.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("[email protected]", FILTER_VALIDATE_EMAIL); // "[email protected]" 或 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 章 — 运算符