PHP数据处理与类型转换精要
PHP的类型系统灵活但容易踩坑。类型转换的规则如果不清楚,debug的时候会怀疑人生。今天把PHP的类型转换规则和数据处理的要点说清楚。
先说说类型转换的规则。PHP有两种类型转换:自动转换和强制转换。
```php
// 强制类型转换
$str = '123';
$int = (int)$str;
$float = (float)$str;
$bool = (bool)$str;
$array = (array)$str;
var_dump($int, $float, $bool, $array);
// 字符串转数字的规则
echo "123abc转数字: " . (int)'123abc' . "\n";
echo "abc转数字: " . (int)'abc' . "\n";
echo "3.14转整数: " . (int)3.14 . "\n";
echo "null转整数: " . (int)null . "\n";
// 布尔值转换规则
var_dump((bool)'0'); // false
var_dump((bool)'0.0'); // true
var_dump((bool)''); // false
var_dump((bool)[]); // false
var_dump((bool)[0]); // true
var_dump((bool)'false');// true
?>
```
isset、empty、is_null的区别是PHP面试常考题:
```php
$values = [
'null' => null,
'空字符串' => '',
'零' => 0,
'零字符串' => '0',
'false' => false,
'空数组' => [],
'有值' => 'hello',
'未定义' => null,
];
// isset: 变量存在且不为null
// empty: 变量存在且为空(""、0、"0"、null、false、[])
// is_null: 变量存在且为null
$results = [];
foreach ($values as $name => $value) {
$results[$name] = [
'isset' => isset($value),
'empty' => empty($value),
'is_null' => is_null($value),
];
}
// 未定义变量
$results['未定义变量'] = [
'isset' => isset($undefinedVar),
'empty' => empty($undefinedVar),
'is_null' => @is_null($undefinedVar),
];
print_r($results);
?>
```
三元运算符和null合并运算符的区别:
```php
$data = [
'name' => '张三',
'age' => 0,
'email' => '',
];
// 三元运算符
$name = $data['name'] ? $data['name'] : '默认名';
echo "name(三元): $name\n";
// null合并运算符(PHP7+):只检查是否为null
$name = $data['name'] ?? '默认名';
echo "name(??): $name\n";
$age = $data['age'] ?? 18;
echo "age(??): $age\n"; // 0,因为0不是null
// 结合empty的null合并
$email = !empty($data['email']) ? $data['email'] : '默认邮箱';
echo "email(empty): $email\n";
// PHP7.4+的??=
$config = ['host' => 'localhost'];
$config['port'] ??= 3306;
$config['host'] ??= '127.0.0.1';
echo "port: {$config['port']}, host: {$config['host']}\n";
?>
```
类型安全的比较:
```php
// == 和 === 的区别
$compare = [
[123, '123', '=='],
[123, '123', '==='],
[0, false, '=='],
[0, false, '==='],
[null, '', '=='],
[null, '', '==='],
['0', false, '=='],
['0', false, '==='],
[[], false, '=='],
[[], false, '==='],
[0, '0', '=='],
[0, '0', '==='],
];
echo str_pad('A', 12) . str_pad('B', 12) . str_pad('==', 8) . "===\n";
echo str_repeat('-', 40) . "\n";
foreach ($compare as [$a, $b, $op]) {
$v1 = var_export($a, true);
$v2 = var_export($b, true);
$loose = $a == $b ? 'true' : 'false';
$strict = $a === $b ? 'true' : 'false';
echo str_pad($v1, 12) . str_pad($v2, 12) . str_pad($loose, 8) . $strict . "\n";
}
?>
```
JSON编码解码的注意事项:
```php
// JSON编码选项
$data = [
'name' => '张三',
'email' => 'test@example.com',
'scores' => [95, 87, 92],
'address' => [
'city' => '北京',
'district' => null,
],
];
// 默认JSON编码
echo json_encode($data) . "\n";
// 带选项的JSON编码
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
// JSON解码
$json = '{"name":"张三","age":28,"active":true,"score":null}';
$decoded = json_decode($json, true);
echo "姓名: {$decoded['name']}\n";
echo "年龄: {$decoded['age']}\n";
echo "活跃: " . ($decoded['active'] ? '是' : '否') . "\n";
echo "分数: " . var_export($decoded['score'], true) . "\n";
// JSON错误处理
$invalidJson = '{name: "test",}';
$result = json_decode($invalidJson, true);
if (json_last_error() !== JSON_ERROR_NONE) {
echo "JSON解析错误: " . json_last_error_msg() . "\n";
}
?>
?>
序列化和反序列化的安全注意事项:
```php
// serialize和unserialize
class User
{
public string $name;
protected string $email;
private string $password;
public function __construct(string $name, string $email, string $password)
{
$this->name = $name;
$this->email = $email;
$this->password = $password;
}
}
$user = new User('张三', 'test@test.com', 'secret123');
$serialized = serialize($user);
echo "序列化: $serialized\n";
// 反序列化
$restored = unserialize($serialized);
echo "反序列化: {$restored->name}\n";
// 安全的JSON序列化(推荐)
$safeData = ['name' => '张三', 'email' => 'test@test.com'];
$json = json_encode($safeData, JSON_UNESCAPED_UNICODE);
$decoded = json_decode($json, true);
echo "JSON序列化: {$decoded['name']}\n";
?>
```
PHP的类型转换规则虽然灵活,但也容易出错。建议始终使用===而不是==,开启strict_types模式,用类型声明约束函数参数和返回值。这些实践能大大减少类型相关的bug。
PHP数据处理与类型转换精要