返回值
函数的返回值是函数执行完成后向外传递结果的方式。理解返回值的概念和用法,能够让我们编写出更强大、更灵活的函数。
返回值的基本概念
什么是返回值?
返回值是函数执行后向调用者返回的结果。它就像是函数的"输出接口",让函数能够将处理结果传递给其他代码继续使用。
<?php
// 简单的返回值示例
function addNumbers($a, $b) {
$sum = $a + $b;
return $sum; // 返回计算结果
}
$result = addNumbers(5, 3); // 接收返回值
echo "5 + 3 = $result"; // 输出:5 + 3 = 8
?>
return 语句的作用
return 语句有两个主要作用:
- 返回值:将结果传递给调用者
- 终止函数:立即结束函数执行
<?php
function checkNumber($number) {
if ($number > 0) {
return "正数"; // 返回并终止函数
} elseif ($number < 0) {
return "负数"; // 返回并终止函数
} else {
return "零"; // 返回并终止函数
}
// 这行代码永远不会执行,因为前面已经有return语句
echo "这句话不会显示";
}
echo checkNumber(10); // 输出:正数
echo checkNumber(-5); // 输出:负数
echo checkNumber(0); // 输出:零
?>
基本返回值类型
返回简单数据类型
<?php
// 返回整数
function getAge() {
return 25;
}
// 返回浮点数
function getPrice() {
return 99.99;
}
// 返回字符串
function getUserName() {
return "张三";
}
// 返回布尔值
function isAdmin() {
return true;
}
// 返回数组
function getUserInfo() {
return [
'name' => '李四',
'age' => 30,
'email' => 'lisi@example.com'
];
}
// 使用各种返回值
echo "年龄:" . getAge() . "<br>";
echo "价格:" . getPrice() . "<br>";
echo "用户名:" . getUserName() . "<br>";
echo "是否管理员:" . (isAdmin() ? "是" : "否") . "<br>";
$userInfo = getUserInfo();
echo "用户信息:{$userInfo['name']}, {$userInfo['age']}岁<br>";
?>
返回 null
<?php
function findUserById($userId) {
$users = [
1 => '张三',
2 => '李四',
3 => '王五'
];
if (isset($users[$userId])) {
return $users[$userId]; // 找到用户,返回用户名
} else {
return null; // 没找到用户,返回null
}
}
$user1 = findUserById(1);
if ($user1 !== null) {
echo "找到用户:$user1<br>";
} else {
echo "用户不存在<br>";
}
$user2 = findUserById(99);
if ($user2 !== null) {
echo "找到用户:$user2<br>";
} else {
echo "用户不存在<br>";
}
?>
返回值类型声明
PHP 7.0+ 支持返回值类型声明,可以指定函数应该返回什么类型的数据。
基本类型声明
<?php
// 声明返回整数
function calculateSum(int $a, int $b): int {
return $a + $b;
}
// 声明返回字符串
function formatName(string $firstName, string $lastName): string {
return $firstName . ' ' . $lastName;
}
// 声明返回浮点数
function calculateAverage(array $numbers): float {
return array_sum($numbers) / count($numbers);
}
// 声明返回布尔值
function isValidEmail(string $email): bool {
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
// 声明返回数组
function getEvenNumbers(int $limit): array {
$evenNumbers = [];
for ($i = 2; $i <= $limit; $i += 2) {
$evenNumbers[] = $i;
}
return $evenNumbers;
}
// 测试类型声明的函数
echo "5 + 3 = " . calculateSum(5, 3) . "<br>";
echo "姓名:" . formatName("张", "三") . "<br>";
echo "平均值:" . calculateAverage([1, 2, 3, 4, 5]) . "<br>";
echo "邮箱是否有效:" . (isValidEmail("test@example.com") ? "是" : "否") . "<br>";
echo "偶数:" . implode(', ', getEvenNumbers(10)) . "<br>";
?>
可空返回类型
<?php
// 返回字符串或null
function findUserName(int $userId): ?string {
$users = [
1 => '张三',
2 => '李四'
];
return $users[$userId] ?? null;
}
// 返回数组或null
function getUserSettings(int $userId): ?array {
$settings = [
1 => ['theme' => 'light', 'notifications' => true],
2 => ['theme' => 'dark', 'notifications' => false]
];
return $settings[$userId] ?? null;
}
// 使用可空返回类型
$userName = findUserName(1);
echo "用户1姓名:" . ($userName ?? "不存在") . "<br>";
$userName = findUserName(99);
echo "用户99姓名:" . ($userName ?? "不存在") . "<br>";
$settings = getUserSettings(1);
if ($settings !== null) {
echo "用户1设置:主题={$settings['theme']}, 通知=" . ($settings['notifications'] ? "开启" : "关闭") . "<br>";
}
?>
联合返回类型(PHP 8.0+)
<?php
// 返回字符串或整数
function processData($data): string|int {
if (is_numeric($data)) {
return (int)$data;
} else {
return (string)$data;
}
}
// 返回数组或字符串
function getConfig(string $key): array|string {
$configs = [
'database' => ['host' => 'localhost', 'port' => 3306],
'version' => '1.0.0'
];
return $configs[$key] ?? "配置不存在";
}
// 测试联合类型
echo processData(123) . "<br>"; // 输出:123 (整数)
echo processData("hello") . "<br>"; // 输出:hello (字符串)
$dbConfig = getConfig('database');
if (is_array($dbConfig)) {
echo "数据库配置:{$dbConfig['host']}:{$dbConfig['port']}<br>";
}
echo "版本:" . getConfig('version') . "<br>";
?>
多返回值处理
PHP函数本身只能返回一个值,但我们可以通过数组、对象等方式实现多返回值的效果。
使用数组返回多个值
<?php
// 返回用户信息数组
function getUserDetails(int $userId): array {
// 模拟数据库查询
$users = [
1 => [
'name' => '张三',
'age' => 25,
'email' => 'zhangsan@example.com',
'is_active' => true
]
];
$user = $users[$userId] ?? null;
if ($user === null) {
return ['success' => false, 'message' => '用户不存在'];
}
return [
'success' => true,
'data' => $user
];
}
// 使用列表结构提取返回值
function getStudentStats(int $studentId): array {
// 模拟学生数据
$students = [
1 => ['chinese' => 85, 'math' => 92, 'english' => 88]
];
$scores = $students[$studentId] ?? [0, 0, 0];
$total = $scores['chinese'] + $scores['math'] + $scores['english'];
$average = $total / 3;
return [$total, $average, $scores]; // 返回多个值
}
// 提取多个返回值
[$totalScore, $averageScore, $subjectScores] = getStudentStats(1);
echo "总分:$totalScore<br>";
echo "平均分:" . round($averageScore, 2) . "<br>";
echo "各科成绩:语文{$subjectScores['chinese']}, 数学{$subjectScores['math']}, 英语{$subjectScores['english']}<br>";
// 更复杂的示例:计算器函数
function advancedCalculator(float $a, float $b, string $operation): array {
$results = [];
switch ($operation) {
case '+':
$results['sum'] = $a + $b;
break;
case '-':
$results['difference'] = $a - $b;
break;
case '*':
$results['product'] = $a * $b;
break;
case '/':
if ($b != 0) {
$results['quotient'] = $a / $b;
$results['remainder'] = $a % $b;
} else {
$results['error'] = '除数不能为零';
}
break;
default:
$results['error'] = '不支持的操作';
}
$results['operation'] = "$a $operation $b";
$results['timestamp'] = date('Y-m-d H:i:s');
return $results;
}
// 使用多返回值计算器
$calcResult = advancedCalculator(10, 3, '/');
foreach ($calcResult as $key => $value) {
echo "$key: $value<br>";
}
?>
使用对象返回多个值
<?php
// 定义结果对象
class OperationResult {
public $success;
public $data;
public $message;
public $timestamp;
public function __construct($success, $data = null, $message = '') {
$this->success = $success;
$this->data = $data;
$this->message = $message;
$this->timestamp = date('Y-m-d H:i:s');
}
}
// 用户管理类
class UserManager {
public function authenticateUser(string $username, string $password): OperationResult {
// 模拟用户数据库
$users = [
'admin' => ['password' => 'admin123', 'role' => 'admin', 'id' => 1],
'user' => ['password' => 'user123', 'role' => 'user', 'id' => 2]
];
if (!isset($users[$username])) {
return new OperationResult(false, null, '用户名不存在');
}
$user = $users[$username];
if ($user['password'] !== $password) {
return new OperationResult(false, null, '密码错误');
}
// 认证成功,返回用户信息(不含密码)
$userData = [
'id' => $user['id'],
'username' => $username,
'role' => $user['role']
];
return new OperationResult(true, $userData, '认证成功');
}
}
// 使用对象返回值
$userManager = new UserManager();
$authResult = $userManager->authenticateUser('admin', 'admin123');
if ($authResult->success) {
echo "登录成功!用户信息:<br>";
echo "ID: {$authResult->data['id']}<br>";
echo "用户名: {$authResult->data['username']}<br>";
echo "角色: {$authResult->data['role']}<br>";
echo "时间: {$authResult->timestamp}<br>";
} else {
echo "登录失败:" . $authResult->message . "<br>";
}
?>
早期返回模式
早期返回(Early Return)是一种编程模式,通过在函数早期处理错误情况或简单情况,使代码更清晰。
复杂的条件处理
<?php
// 不好的做法:深层嵌套
function processOrderBad($order) {
if ($order !== null) {
if (isset($order['items']) && !empty($order['items'])) {
if (isset($order['customer']) && !empty($order['customer'])) {
if ($order['total'] > 0) {
// 处理订单逻辑
return "订单处理成功";
} else {
return "订单金额必须大于0";
}
} else {
return "缺少客户信息";
}
} else {
return "订单中没有商品";
}
} else {
return "订单数据为空";
}
}
// 好的做法:早期返回
function processOrder($order): string {
// 早期检查错误情况
if ($order === null) {
return "订单数据为空";
}
if (!isset($order['items']) || empty($order['items'])) {
return "订单中没有商品";
}
if (!isset($order['customer']) || empty($order['customer'])) {
return "缺少客户信息";
}
if ($order['total'] <= 0) {
return "订单金额必须大于0";
}
// 主要逻辑
return "订单处理成功";
}
// 测试
$testOrder = [
'items' => ['商品1', '商品2'],
'customer' => ['name' => '张三'],
'total' => 100
];
echo processOrder($testOrder) . "<br>";
echo processOrder(null) . "<br>";
?>
参数验证的早期返回
<?php
// 注册用户函数 - 使用早期返回验证
function registerUser($userData): array {
// 验证必填字段
if (!isset($userData['username']) || empty(trim($userData['username']))) {
return ['success' => false, 'message' => '用户名不能为空'];
}
if (!isset($userData['email']) || empty(trim($userData['email']))) {
return ['success' => false, 'message' => '邮箱不能为空'];
}
if (!isset($userData['password']) || strlen($userData['password']) < 6) {
return ['success' => false, 'message' => '密码至少6个字符'];
}
// 验证邮箱格式
if (!filter_var($userData['email'], FILTER_VALIDATE_EMAIL)) {
return ['success' => false, 'message' => '邮箱格式不正确'];
}
// 验证用户名长度
if (strlen($userData['username']) < 3 || strlen($userData['username']) > 20) {
return ['success' => false, 'message' => '用户名必须在3-20个字符之间'];
}
// 所有验证通过,开始注册流程
$user = [
'id' => uniqid(),
'username' => $userData['username'],
'email' => $userData['email'],
'password_hash' => password_hash($userData['password'], PASSWORD_DEFAULT),
'created_at' => date('Y-m-d H:i:s'),
'status' => 'active'
];
// 模拟保存到数据库
saveUser($user);
return [
'success' => true,
'message' => '注册成功',
'user_id' => $user['id']
];
}
function saveUser($user) {
// 模拟保存操作
return true;
}
// 测试注册
$testUsers = [
['username' => 'test', 'email' => 'test@example.com', 'password' => 'password123'],
['username' => '', 'email' => 'test@example.com', 'password' => 'password123'],
['username' => 'test', 'email' => 'invalid-email', 'password' => 'password123']
];
foreach ($testUsers as $userData) {
$result = registerUser($userData);
echo $result['message'] . "<br>";
}
?>
返回值 vs 引用传递
有时候我们可以选择返回值或引用传递来修改数据。理解两者的区别很重要。
返回修改后的副本
<?php
// 返回修改后的数组副本
function addTaxToPrices(array $prices, float $taxRate): array {
$pricesWithTax = [];
foreach ($prices as $price) {
$pricesWithTax[] = $price * (1 + $taxRate);
}
return $pricesWithTax;
}
// 原数组不会被修改
$originalPrices = [100, 200, 300];
$taxedPrices = addTaxToPrices($originalPrices, 0.1);
echo "原价格:" . implode(', ', $originalPrices) . "<br>";
echo "含税价格:" . implode(', ', $taxedPrices) . "<br>";
?>
使用引用传递修改原数据
<?php
// 通过引用传递修改原数组
function addTaxToPricesRef(array &$prices, float $taxRate): void {
foreach ($prices as &$price) {
$price = $price * (1 + $taxRate);
}
// 不需要返回值,因为原数组已经被修改
}
// 原数组会被修改
$prices = [100, 200, 300];
echo "修改前:" . implode(', ', $prices) . "<br>";
addTaxToPricesRef($prices, 0.1);
echo "修改后:" . implode(', ', $prices) . "<br>";
?>
链式调用(返回$this)
在面向对象编程中,返回$this可以实现方法链式调用。
<?php
class QueryBuilder {
private $query = '';
private $params = [];
public function select(string $columns): self {
$this->query = "SELECT $columns";
return $this; // 返回自身以支持链式调用
}
public function from(string $table): self {
$this->query .= " FROM $table";
return $this;
}
public function where(string $condition, $value): self {
$this->query .= " WHERE $condition";
$this->params[] = $value;
return $this;
}
public function orderBy(string $column, string $direction = 'ASC'): self {
$this->query .= " ORDER BY $column $direction";
return $this;
}
public function getQuery(): string {
return $this->query;
}
public function getParams(): array {
return $this->params;
}
}
// 使用链式调用
$queryBuilder = new QueryBuilder();
$query = $queryBuilder
->select('name, email, age')
->from('users')
->where('age > ?', 18)
->orderBy('name', 'ASC')
->getQuery();
echo "生成的SQL查询:$query<br>";
?>
异常处理与返回值
使用异常 vs 返回错误码
<?php
// 方式1:返回错误码/错误信息
function divideWithReturn($a, $b) {
if ($b == 0) {
return ['success' => false, 'message' => '除数不能为零'];
}
return ['success' => true, 'result' => $a / $b];
}
// 方式2:抛出异常
function divideWithException($a, $b) {
if ($b == 0) {
throw new InvalidArgumentException('除数不能为零');
}
return $a / $b;
}
// 使用返回错误码的方式
$result1 = divideWithReturn(10, 2);
if ($result1['success']) {
echo "结果:" . $result1['result'] . "<br>";
} else {
echo "错误:" . $result1['message'] . "<br>";
}
// 使用异常的方式
try {
$result2 = divideWithException(10, 0);
echo "结果:$result2<br>";
} catch (InvalidArgumentException $e) {
echo "错误:" . $e->getMessage() . "<br>";
}
?>
自定义异常类
<?php
// 自定义异常类
class ValidationException extends Exception {
private $errors;
public function __construct(array $errors, string $message = "数据验证失败") {
parent::__construct($message);
$this->errors = $errors;
}
public function getErrors(): array {
return $this->errors;
}
}
class UserRegistrationService {
public function registerUser($userData): array {
$this->validateUserData($userData);
// 如果验证通过,继续注册流程
$userId = $this->saveUser($userData);
return [
'success' => true,
'user_id' => $userId,
'message' => '注册成功'
];
}
private function validateUserData($userData): void {
$errors = [];
if (empty($userData['username'])) {
$errors[] = '用户名不能为空';
}
if (empty($userData['email'])) {
$errors[] = '邮箱不能为空';
}
if (!filter_var($userData['email'], FILTER_VALIDATE_EMAIL)) {
$errors[] = '邮箱格式不正确';
}
if (!empty($errors)) {
throw new ValidationException($errors);
}
}
private function saveUser($userData): string {
// 模拟保存用户
return uniqid('user_');
}
}
// 使用自定义异常
$registrationService = new UserRegistrationService();
try {
$result = $registrationService->registerUser([
'username' => 'testuser',
'email' => 'invalid-email'
]);
echo $result['message'] . "<br>";
} catch (ValidationException $e) {
echo $e->getMessage() . "<br>";
echo "具体错误:<br>";
foreach ($e->getErrors() as $error) {
echo "- $error<br>";
}
}
?>
实际应用示例
文件处理器
<?php
class FileProcessor {
// 读取文件内容
public function readFile(string $filePath): array {
if (!file_exists($filePath)) {
return [
'success' => false,
'message' => '文件不存在',
'content' => null
];
}
if (!is_readable($filePath)) {
return [
'success' => false,
'message' => '文件不可读',
'content' => null
];
}
$content = file_get_contents($filePath);
if ($content === false) {
return [
'success' => false,
'message' => '读取文件失败',
'content' => null
];
}
return [
'success' => true,
'message' => '文件读取成功',
'content' => $content,
'size' => filesize($filePath),
'type' => mime_content_type($filePath)
];
}
// 写入文件内容
public function writeFile(string $filePath, string $content): array {
$directory = dirname($filePath);
// 检查目录是否存在
if (!is_dir($directory)) {
if (!mkdir($directory, 0755, true)) {
return [
'success' => false,
'message' => '无法创建目录',
'bytes_written' => 0
];
}
}
// 写入文件
$bytesWritten = file_put_contents($filePath, $content);
if ($bytesWritten === false) {
return [
'success' => false,
'message' => '写入文件失败',
'bytes_written' => 0
];
}
return [
'success' => true,
'message' => '文件写入成功',
'bytes_written' => $bytesWritten,
'file_path' => $filePath
];
}
// 备份文件
public function backupFile(string $filePath): array {
$result = $this->readFile($filePath);
if (!$result['success']) {
return $result;
}
$backupPath = $filePath . '.backup.' . date('Y-m-d_H-i-s');
return $this->writeFile($backupPath, $result['content']);
}
}
// 使用文件处理器
$processor = new FileProcessor();
// 写入测试文件
$writeResult = $processor->writeFile('test/sample.txt', '这是一个测试文件内容');
echo "写入结果:" . ($writeResult['success'] ? '成功' : '失败') . "<br>";
if ($writeResult['success']) {
echo "写入字节数:" . $writeResult['bytes_written'] . "<br>";
}
// 读取文件
$readResult = $processor->readFile('test/sample.txt');
echo "读取结果:" . ($readResult['success'] ? '成功' : '失败') . "<br>";
if ($readResult['success']) {
echo "文件内容:" . $readResult['content'] . "<br>";
echo "文件大小:" . $readResult['size'] . " 字节<br>";
echo "文件类型:" . $readResult['type'] . "<br>";
}
// 备份文件
$backupResult = $processor->backupFile('test/sample.txt');
echo "备份结果:" . ($backupResult['success'] ? '成功' : '失败') . "<br>";
?>
数据分析器
<?php
class DataAnalyzer {
// 分析数字数组
public function analyzeNumbers(array $numbers): array {
if (empty($numbers)) {
return [
'success' => false,
'message' => '数据为空',
'statistics' => null
];
}
// 验证所有元素都是数字
foreach ($numbers as $number) {
if (!is_numeric($number)) {
return [
'success' => false,
'message' => '数据包含非数字元素',
'statistics' => null
];
}
}
$numbers = array_map('floatval', $numbers);
sort($numbers);
$count = count($numbers);
$statistics = [
'count' => $count,
'sum' => array_sum($numbers),
'mean' => array_sum($numbers) / $count,
'min' => min($numbers),
'max' => max($numbers),
'median' => $this->calculateMedian($numbers),
'range' => max($numbers) - min($numbers),
'variance' => $this->calculateVariance($numbers),
'standard_deviation' => $this->calculateStandardDeviation($numbers)
];
return [
'success' => true,
'message' => '分析完成',
'statistics' => $statistics
];
}
// 计算中位数
private function calculateMedian(array $sortedNumbers): float {
$count = count($sortedNumbers);
$middle = floor($count / 2);
if ($count % 2 === 0) {
return ($sortedNumbers[$middle - 1] + $sortedNumbers[$middle]) / 2;
} else {
return $sortedNumbers[$middle];
}
}
// 计算方差
private function calculateVariance(array $numbers): float {
$mean = array_sum($numbers) / count($numbers);
$squaredDiffs = array_map(function($num) use ($mean) {
return pow($num - $mean, 2);
}, $numbers);
return array_sum($squaredDiffs) / count($numbers);
}
// 计算标准差
private function calculateStandardDeviation(array $numbers): float {
return sqrt($this->calculateVariance($numbers));
}
// 生成分析报告
public function generateReport(array $numbers): string {
$analysis = $this->analyzeNumbers($numbers);
if (!$analysis['success']) {
return "错误:" . $analysis['message'];
}
$stats = $analysis['statistics'];
$report = "=== 数据分析报告 ===\n";
$report .= "数据个数:{$stats['count']}\n";
$report .= "总和:" . number_format($stats['sum'], 2) . "\n";
$report .= "平均值:" . number_format($stats['mean'], 2) . "\n";
$report .= "中位数:" . number_format($stats['median'], 2) . "\n";
$report .= "最小值:" . number_format($stats['min'], 2) . "\n";
$report .= "最大值:" . number_format($stats['max'], 2) . "\n";
$report .= "极差:" . number_format($stats['range'], 2) . "\n";
$report .= "方差:" . number_format($stats['variance'], 2) . "\n";
$report .= "标准差:" . number_format($stats['standard_deviation'], 2) . "\n";
$report .= "==================\n";
return $report;
}
}
// 使用数据分析器
$analyzer = new DataAnalyzer();
// 测试数据
$testData1 = [10, 20, 30, 40, 50];
$testData2 = [85, 92, 78, 65, 88, 95, 72, 58];
$testData3 = []; // 空数据
$testData4 = [10, 20, 'invalid', 30]; // 包含非数字
// 分析数据
$dataSets = [
'数据集1' => $testData1,
'数据集2' => $testData2,
'空数据' => $testData3,
'无效数据' => $testData4
];
foreach ($dataSets as $name => $data) {
echo "<h4>$name</h4>";
if (!empty($data)) {
echo "数据:" . implode(', ', $data) . "<br>";
}
$result = $analyzer->analyzeNumbers($data);
if ($result['success']) {
$stats = $result['statistics'];
echo "分析结果:<br>";
echo "- 平均值:" . number_format($stats['mean'], 2) . "<br>";
echo "- 标准差:" . number_format($stats['standard_deviation'], 2) . "<br>";
echo "- 中位数:" . number_format($stats['median'], 2) . "<br>";
} else {
echo "错误:" . $result['message'] . "<br>";
}
echo "<br>";
}
// 生成完整报告
echo "<h4>完整分析报告</h4>";
echo "<pre>" . nl2br($analyzer->generateReport($testData2)) . "</pre>";
?>
最佳实践
1. 明确的返回值类型
<?php
// 好的做法:明确的返回值类型声明
function calculateDiscount(float $price, float $percentage): float {
if ($percentage < 0 || $percentage > 100) {
throw new InvalidArgumentException('折扣百分比必须在0-100之间');
}
return $price * (1 - $percentage / 100);
}
// 不好的做法:不明确的返回值
function calculateDiscountBad($price, $percentage) {
// 可能返回整数、浮点数、字符串或null
if ($price < 0) {
return "价格不能为负数";
}
return $price * (1 - $percentage / 100);
}
?>
2. 一致的返回值格式
<?php
// 好的做法:一致的返回值格式
function apiResponse($data, string $message = '', bool $success = true): array {
return [
'success' => $success,
'message' => $message,
'data' => $data,
'timestamp' => date('Y-m-d H:i:s')
];
}
// 使用一致的返回格式
function getUserData($userId): array {
$user = findUserInDatabase($userId);
if ($user) {
return apiResponse($user, '获取用户数据成功');
} else {
return apiResponse(null, '用户不存在', false);
}
}
?>
3. 避免混合返回类型
<?php
// 不好的做法:混合返回类型
function findUser($id) {
if ($id == 1) {
return ['name' => '张三']; // 返回数组
} elseif ($id == 2) {
return "李四"; // 返回字符串
} else {
return false; // 返回布尔值
}
}
// 好的做法:统一的返回类型
function findUserFixed($id): ?array {
$users = [
1 => ['name' => '张三'],
2 => ['name' => '李四']
];
return $users[$id] ?? null;
}
?>
4. 使用适当的错误处理
<?php
// 对于可以预期的情况,返回错误信息
function validateEmail(string $email): array {
if (empty($email)) {
return ['valid' => false, 'error' => '邮箱不能为空'];
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return ['valid' => false, 'error' => '邮箱格式不正确'];
}
return ['valid' => true, 'error' => null];
}
// 对于意外情况,抛出异常
function connectToDatabase(string $host, string $username, string $password): PDO {
try {
return new PDO("mysql:host=$host", $username, $password);
} catch (PDOException $e) {
throw new RuntimeException("数据库连接失败: " . $e->getMessage());
}
}
?>
常见错误和解决方案
1. 忘记返回值
<?php
// 错误:忘记返回值
function calculateTax($amount) {
$tax = $amount * 0.1;
// 忘记return $tax;
}
// 解决方案:确保有返回语句
function calculateTaxFixed($amount) {
$tax = $amount * 0.1;
return $tax; // 添加return语句
}
?>
2. 返回值类型不匹配
<?php
// 声明返回字符串,但可能返回null
function getUserName(int $userId): string {
$users = [1 => '张三'];
return $users[$userId] ?? null; // 可能返回null,违反类型声明
}
// 解决方案1:使用可空类型
function getUserNameFixed1(int $userId): ?string {
$users = [1 => '张三'];
return $users[$userId] ?? null;
}
// 解决方案2:提供默认值
function getUserNameFixed2(int $userId): string {
$users = [1 => '张三'];
return $users[$userId] ?? '未知用户';
}
?>
3. 过度使用返回值
<?php
// 不好的做法:函数做多件事还返回复杂结构
function processAndSaveAndNotify($data): array {
// 处理数据
$processed = processData($data);
// 保存数据
$saved = saveData($processed);
// 发送通知
$notified = sendNotification($saved);
return [
'processed' => $processed,
'saved' => $saved,
'notified' => $notified
];
}
// 好的做法:函数职责单一
function processData($data): array {
// 只处理数据
return $data;
}
function saveData($data): bool {
// 只保存数据
return true;
}
function sendNotification($data): bool {
// 只发送通知
return true;
}
?>
练习题
基础练习
-
简单计算函数
<?php // 创建计算函数,返回不同运算的结果 function calculate($a, $b, $operation) { // 返回运算结果 } echo calculate(10, 5, '+'); // 应该输出:15 echo calculate(10, 5, '-'); // 应该输出:5 echo calculate(10, 5, '*'); // 应该输出:50 ?> -
数组处理函数
<?php // 创建函数处理数组,返回统计信息 function analyzeArray($numbers) { // 返回包含最大值、最小值、平均值、和的数组 } $stats = analyzeArray([1, 5, 3, 9, 2]); print_r($stats); ?> -
字符串验证函数
<?php // 创建邮箱验证函数,返回验证结果和错误信息 function validateEmail($email) { // 返回 ['valid' => bool, 'message' => string] } $result = validateEmail('test@example.com'); print_r($result); ?>
进阶练习
-
用户认证系统
<?php // 创建用户认证函数,包含登录验证和权限检查 function authenticateUser($username, $password) { // 返回包含success、user_info、token、permissions的数组 } $result = authenticateUser('admin', 'password123'); print_r($result); ?> -
文件操作类
<?php class FileManager { public function readFile($filePath) { // 返回包含success、content、size、error的数组 } public function writeFile($filePath, $content) { // 返回包含success、bytes_written、error的数组 } } // 测试文件管理器 ?>
实战练习
-
电商价格计算器
<?php // 创建完整的电商价格计算器 function calculateProductPrice($basePrice, $quantity, $discount = 0, $tax = 0.08) { // 返回详细的价格信息数组 } $priceInfo = calculateProductPrice(100, 3, 10, 0.08); print_r($priceInfo); ?> -
数据验证器
<?php class DataValidator { public function validateUserData($userData) { // 验证用户数据,返回验证结果 } public function validateProductData($productData) { // 验证商品数据,返回验证结果 } } // 创建完整的数据验证系统 ?>
总结
返回值是函数与外部世界沟通的重要桥梁。通过本章的学习,你应该能够:
- 理解return语句的作用和用法
- 掌握不同类型的返回值处理
- 使用返回值类型声明提高代码质量
- 实现多返回值的各种技巧
- 应用早期返回模式优化代码结构
- 选择合适的错误处理方式
- 在实际项目中遵循最佳实践
记住,好的返回值设计可以让函数更容易使用、测试和维护。在实际开发中,要始终考虑返回值的一致性、明确性和易用性。
下一章我们将学习变量作用域,了解函数内外变量的关系和访问规则。