数据类型
概述
PHP是一种动态类型语言,意味着变量不需要显式的类型声明。然而,理解PHP的数据类型对于编写健壮的应用程序至关重要。本章涵盖所有PHP数据类型、类型转换、类型检查和类型声明。
标量类型
字符串
字符串是用于存储和操作文本的字符序列。
php
<?php
// 单引号 - 字面字符串
$name = '张三';
$message = '你好,世界!';
// 双引号 - 变量插值
$greeting = "你好,$name!";
$path = "C:\Users\$name\Documents";
// 双引号中的转义序列
$text = "第一行\n第二行\t制表符";
$quote = '他说"你好"';
// 字符串长度
echo strlen($name); // 6(中文字符可能不同)
// 字符串函数
echo strtoupper($name); // 张三(可能不支持中文)
echo strtolower($name); // 张三(可能不支持中文)
echo ucfirst($name); // 张三
echo ucwords($name); // 张三
?>Heredoc和Nowdoc
php
<?php
$name = "小红";
// Heredoc - 类似双引号
$html = <<<HTML
<div class="user">
<h1>欢迎,$name!</h1>
<p>这里支持变量插值。</p>
</div>
HTML;
// Nowdoc - 类似单引号
$config = <<<'CONFIG'
server_name = localhost
database = myapp
user = $name // 这里不会被插值
CONFIG;
echo $html;
echo $config;
?>整数
整数是没有小数点的完整数字。
php
<?php
$decimal = 123; // 十进制
$octal = 0123; // 八进制(十进制83)
$hex = 0x1A; // 十六进制(十进制26)
$binary = 0b1010; // 二进制(十进制10,PHP 5.4+)
// 整数限制
echo PHP_INT_MAX; // 最大整数值
echo PHP_INT_MIN; // 最小整数值
echo PHP_INT_SIZE; // 字节大小
// 类型检查
var_dump(is_int($decimal)); // true
var_dump(is_integer($decimal)); // true(别名)
// 整数运算
$a = 10;
$b = 3;
echo $a + $b; // 13
echo $a - $b; // 7
echo $a * $b; // 30
echo $a / $b; // 3.333...(变成浮点数)
echo $a % $b; // 1(取模)
echo $a ** $b; // 1000(幂运算,PHP 5.6+)
?>浮点数 (Float/Double)
浮点数表示带有小数点的数值。
php
<?php
$price = 19.99;
$scientific = 1.23e4; // 12300
$negative = -3.14;
// 浮点数精度问题
$result = 0.1 + 0.2;
var_dump($result); // 0.30000000000000004
var_dump($result == 0.3); // false
// 正确的浮点数比较
function floatEquals($a, $b, $epsilon = 0.00001) {
return abs($a - $b) < $epsilon;
}
var_dump(floatEquals(0.1 + 0.2, 0.3)); // true
// 浮点数函数
echo round(3.7); // 4
echo floor(3.7); // 3
echo ceil(3.2); // 4
echo number_format(1234.567, 2); // "1,234.57"
// 类型检查
var_dump(is_float($price)); // true
var_dump(is_double($price)); // true(别名)
?>布尔值
布尔值表示 true 或 false 值。
php
<?php
$isActive = true;
$isComplete = false;
// 布尔转换
var_dump((bool) 1); // true
var_dump((bool) 0); // false
var_dump((bool) ""); // false
var_dump((bool) "0"); // false
var_dump((bool) "false"); // true(非空字符串)
var_dump((bool) []); // false(空数组)
var_dump((bool) null); // false
// PHP 中的假值
$falsyValues = [
false,
0,
0.0,
"",
"0",
null,
[]
];
foreach ($falsyValues as $value) {
if (!$value) {
echo "这个值是假值\n";
}
}
// 类型检查
var_dump(is_bool($isActive)); // true
?>复合类型
数组
数组是值的有序集合。
索引数组
php
<?php
// 创建索引数组
$fruits = ["apple", "banana", "orange"];
$numbers = array(1, 2, 3, 4, 5);
// 访问元素
echo $fruits[0]; // "apple"
echo $fruits[1]; // "banana"
// 添加元素
$fruits[] = "grape"; // 附加
$fruits[10] = "mango"; // 指定索引
array_push($fruits, "kiwi"); // 使用函数附加
// 数组函数
echo count($fruits); // 数组长度
echo sizeof($fruits); // count()的别名
var_dump(in_array("apple", $fruits)); // true
// 遍历数组
foreach ($fruits as $fruit) {
echo $fruit . "\n";
}
foreach ($fruits as $index => $fruit) {
echo "$index: $fruit\n";
}
?>关联数组
php
<?php
// 创建关联数组
$person = [
"name" => "John Doe",
"age" => 30,
"email" => "john@example.com",
"active" => true
];
// 访问元素
echo $person["name"]; // "John Doe"
echo $person["age"]; // 30
// 添加/修改元素
$person["city"] = "New York";
$person["age"] = 31;
// 数组函数
$keys = array_keys($person); // 获取所有键
$values = array_values($person); // 获取所有值
var_dump(array_key_exists("name", $person)); // true
// 遍历关联数组
foreach ($person as $key => $value) {
echo "$key: $value\n";
}
?>多维数组
php
<?php
$users = [
[
"id" => 1,
"name" => "John",
"email" => "john@example.com"
],
[
"id" => 2,
"name" => "Jane",
"email" => "jane@example.com"
]
];
// 访问嵌套元素
echo $users[0]["name"]; // "John"
echo $users[1]["email"]; // "jane@example.com"
// 添加嵌套元素
$users[0]["age"] = 30;
// 遍历多维数组
foreach ($users as $user) {
echo "ID: " . $user["id"] . "\n";
echo "Name: " . $user["name"] . "\n";
echo "Email: " . $user["email"] . "\n";
echo "---\n";
}
?>数组操作
php
<?php
$numbers = [1, 2, 3, 4, 5];
// 数组函数
$doubled = array_map(function($n) { return $n * 2; }, $numbers);
$evens = array_filter($numbers, function($n) { return $n % 2 == 0; });
$sum = array_reduce($numbers, function($carry, $n) { return $carry + $n; }, 0);
// 排序
$fruits = ["banana", "apple", "orange"];
sort($fruits); // 排序值
asort($fruits); // 排序值,保持键
ksort($fruits); // 按键排序
// 数组合并和切片
$arr1 = [1, 2, 3];
$arr2 = [4, 5, 6];
$merged = array_merge($arr1, $arr2); // [1, 2, 3, 4, 5, 6]
$slice = array_slice($numbers, 1, 3); // [2, 3, 4]
// 数组搜索
$position = array_search("apple", $fruits);
$exists = in_array("banana", $fruits);
?>对象
对象是封装数据和行为的类实例。
php
<?php
// 简单的类定义
class Person {
public $name;
public $age;
private $email;
public function __construct($name, $age, $email) {
$this->name = $name;
$this->age = $age;
$this->email = $email;
}
public function getEmail() {
return $this->email;
}
public function setEmail($email) {
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->email = $email;
}
}
public function introduce() {
return "你好,我是{$this->name},今年{$this->age}岁。";
}
}
// 创建对象
$person1 = new Person("Alice", 25, "alice@example.com");
$person2 = new Person("Bob", 30, "bob@example.com");
// 访问属性和方法
echo $person1->name; // "Alice"
echo $person1->introduce(); // "你好,我是Alice,今年25岁。"
$person1->setEmail("alice.new@example.com");
// 对象比较
var_dump($person1 == $person2); // false(不同值)
var_dump($person1 === $person2); // false(不同对象)
// 类型检查
var_dump(is_object($person1)); // true
var_dump($person1 instanceof Person); // true
?>stdClass 对象
php
<?php
// 创建 stdClass 对象
$obj = new stdClass();
$obj->name = "John";
$obj->age = 30;
// 将数组转为对象
$array = ["name" => "Jane", "age" => 25];
$obj2 = (object) $array;
echo $obj2->name; // "Jane"
// 将对象转为数组
$backToArray = (array) $obj2;
var_dump($backToArray); // ["name" => "Jane", "age" => 25]
?>特殊类型
NULL
NULL 表示一个没有值的变量。
php
<?php
$var = null;
$undefined; // 也是 null
// NULL 赋值
$name = "John";
$name = null; // 现在是 null
// 类型检查
var_dump(is_null($var)); // true
var_dump($var === null); // true
var_dump(isset($var)); // false
var_dump(empty($var)); // true
// 空合并运算符(PHP 7+)
$username = $_GET['user'] ?? 'guest';
$config = $userConfig ?? $defaultConfig ?? 'fallback';
// 空合并赋值(PHP 7.4+)
$config ??= 'default_value';
?>资源
资源是保存对外部资源引用的特殊变量。
php
<?php
// 文件资源
$file = fopen('data.txt', 'r');
var_dump(is_resource($file)); // true
var_dump(get_resource_type($file)); // "stream"
fclose($file);
// 数据库资源(旧的 MySQL 扩展)
// $connection = mysql_connect('localhost', 'user', 'pass');
// var_dump(is_resource($connection)); // true
// cURL 资源
$curl = curl_init();
var_dump(is_resource($curl)); // true
curl_close($curl);
// 图像资源(GD 扩展)
if (extension_loaded('gd')) {
$image = imagecreate(100, 100);
var_dump(is_resource($image)); // true
imagedestroy($image);
}
?>类型转换和类型推断
自动类型转换
php
<?php
// 字符串转数字
$str = "123";
$num = $str + 0; // 123(整数)
$float = $str + 0.0; // 123.0(浮点数)
// 算数运算
echo "10" + "20"; // 30(两个都转为整数)
echo "10.5" + "20.3"; // 30.8(两个都转为浮点数)
// 字符串连接
echo 10 . 20; // "1020"(两个都转为字符串)
// 布尔上下文
if ("0") { // false
echo "这不会打印";
}
if ("false") { // true(非空字符串)
echo "这会打印";
}
?>显式类型转换
php
<?php
$value = "123.45";
// 转换为不同类型
$int = (int) $value; // 123
$float = (float) $value; // 123.45
$string = (string) $value; // "123.45"
$bool = (bool) $value; // true
$array = (array) $value; // ["123.45"]
$object = (object) $value; // stdClass,属性 "scalar" => "123.45"
// 使用转换函数
$int2 = intval($value); // 123
$float2 = floatval($value); // 123.45
$string2 = strval($value); // "123.45"
// 解析函数
$parsed = parse_url("https://example.com/path?query=value");
$json = json_decode('{"name": "John", "age": 30}', true);
?>类型检查函数
内置类型检查
php
<?php
$var = "Hello";
// 类型检查函数
var_dump(is_string($var)); // true
var_dump(is_int($var)); // false
var_dump(is_float($var)); // false
var_dump(is_bool($var)); // false
var_dump(is_array($var)); // false
var_dump(is_object($var)); // false
var_dump(is_null($var)); // false
var_dump(is_resource($var)); // false
// 通用类型检查
var_dump(gettype($var)); // "string"
// 数字检查
var_dump(is_numeric("123")); // true
var_dump(is_numeric("12.3")); // true
var_dump(is_numeric("abc")); // false
// 标量检查
var_dump(is_scalar($var)); // true(string、int、float、bool)
var_dump(is_scalar([])); // false(数组不是标量)
?>自定义类型检查
php
<?php
function isPositiveInteger($value) {
return is_int($value) && $value > 0;
}
function isValidEmail($email) {
return is_string($email) && filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
function isAssociativeArray($array) {
if (!is_array($array)) {
return false;
}
return array_keys($array) !== range(0, count($array) - 1);
}
// 使用
var_dump(isPositiveInteger(5)); // true
var_dump(isPositiveInteger(-5)); // false
var_dump(isValidEmail("test@example.com")); // true
var_dump(isAssociativeArray(["a" => 1, "b" => 2])); // true
?>类型声明(PHP 7+)
标量类型声明
php
<?php
// 启用严格类型(可选)
declare(strict_types=1);
function add(int $a, int $b): int {
return $a + $b;
}
function divide(float $a, float $b): float {
return $a / $b;
}
function greet(string $name): string {
return "Hello, " . $name;
}
function isActive(bool $status): bool {
return $status;
}
// 使用
echo add(5, 3); // 8
echo divide(10.0, 3.0); // 3.333...
echo greet("Alice"); // "Hello, Alice"
echo isActive(true); // 1 (true)
?>类类型声明
php
<?php
class User {
public $name;
public function __construct(string $name) {
$this->name = $name;
}
}
class UserService {
public function saveUser(User $user): bool {
// 保存用户逻辑
return true;
}
public function getUsers(): array {
// 返回用户数组
return [];
}
}
// 使用
$user = new User("John");
$service = new UserService();
$result = $service->saveUser($user);
?>可空类型(PHP 7.1+)
php
<?php
function findUser(?int $id): ?User {
if ($id === null) {
return null;
}
// 查找用户逻辑
return new User("找到的用户");
}
// 联合类型(PHP 8.0+)
function processId(int|string $id): string {
return "处理 ID:" . $id;
}
// 使用
$user = findUser(null); // 返回 null
$user = findUser(123); // 返回 User 对象
echo processId(123); // "处理 ID:123"
echo processId("abc"); // "处理 ID:abc"
?>处理混合类型
处理未知类型
php
<?php
function processValue($value) {
switch (gettype($value)) {
case 'string':
return strtoupper($value);
case 'integer':
case 'double':
return $value * 2;
case 'boolean':
return $value ? '是' : '否';
case 'array':
return count($value);
case 'object':
return get_class($value);
case 'NULL':
return 'NULL 值';
default:
return '未知类型';
}
}
// 测试不同类型
echo processValue("hello"); // "HELLO"
echo processValue(5); // 10
echo processValue(true); // "是"
echo processValue([1, 2, 3]); // 3
echo processValue(new stdClass()); // "stdClass"
echo processValue(null); // "NULL 值"
?>类型安全函数
php
<?php
function safeAdd($a, $b) {
if (!is_numeric($a) || !is_numeric($b)) {
throw new InvalidArgumentException("两个参数都必须是数字");
}
return $a + $b;
}
function safeArrayAccess(array $array, $key, $default = null) {
return array_key_exists($key, $array) ? $array[$key] : $default;
}
// 使用
try {
echo safeAdd(5, 3); // 8
echo safeAdd("5", "3"); // 8
echo safeAdd("a", "b"); // 抛出异常
} catch (InvalidArgumentException $e) {
echo "错误:" . $e->getMessage();
}
$data = ["name" => "John", "age" => 30];
echo safeArrayAccess($data, "name", "未知"); // "John"
echo safeArrayAccess($data, "email", "无邮箱"); // "无邮箱"
?>下一步
现在您已经了解了PHP的数据类型,让我们在变量和常量中更详细地探讨变量和常量。
实践练习
- 创建函数演示不同数据类型的类型转换
- 构建一个数据验证器,检查多种类型和格式
- 使用类型声明实现类型安全函数
- 创建用于安全类型转换的工具类
- 练习处理多维数组和对象
理解数据类型是编写健壮PHP应用程序的基础!