PHP 15 个高效开发的小技巧

PHP 15 个高效开发的小技巧

在 PHP 开发中,你不需要依赖新框架也能显著提升效率。真正有用的是那些能节省时间、减少重复工作的小技巧。本文将介绍一些简单但强大的 PHP 技巧,帮助你编写更简洁、更健壮的代码。
原文链接-PHP 15 个高效开发的小技巧

让类型系统为你保驾护航

php 复制代码
declare(strict_types=1);

function calculatePriceWithTax(float $price, float $taxRate): float {
    return $price * (1 + $taxRate);
}

优势:类型错误会立即显现,而不是在后期才出现并难以追踪。

使用空值合并和空安全操作符

简化空值检查:

php 复制代码
// 空值合并
$username = $_GET['user'] ?? 'guest';

// 空安全操作符
$street = $order?->customer?->address?->street;

// 空值合并赋值
$config['timeout'] ??= 30;

使用 match 替代 switch

更简洁的条件分支:

php 复制代码
$statusText = match ($statusCode) {
    200, 201 => '成功',
    400      => '错误请求',
    404      => '未找到',
    500      => '服务器错误',
    default  => '未知状态',
};

使用箭头函数简化回调

php 复制代码
$prices = [12.5, 10.0, 3.5];
$pricesWithTax = array_map(fn($price) => round($price * 1.11, 2), $prices);

数组辅助函数

php 复制代码
// 从用户数组中提取邮箱
$emails = array_column($users, 'email');

// 按ID索引
$indexedById = array_column($users, null, 'id');

// 计算购物车总价
$total = array_reduce($cart, 
    fn($sum, $item) => $sum + $item['quantity'] * $item['price'], 
    0.0
);

使用 filter_var 验证输入

php 复制代码
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);
$ip = filter_var($_SERVER['REMOTE_ADDR'] ?? '', FILTER_VALIDATE_IP);

if (!$email) { /* 处理邮箱格式错误 */ }

安全的字符串处理

php 复制代码
// 去除空白字符
$name = trim((string)($_POST['name'] ?? ''));

// 安全比较(防止时序攻击)
if (hash_equals($knownToken, $providedToken)) {
    // 验证通过,继续执行
}

使用 DateTimeImmutable 处理日期

php 复制代码
$timezone = new DateTimeZone('Asia/Shanghai');
$now = new DateTimeImmutable('now', $timezone);
// 计算两天后的上午9点
$deliveryTime = $now->modify('+2 days')->setTime(9, 0);

使用生成器处理大文件

php 复制代码
/**
 * 读取CSV文件生成器
 * @param string $filePath CSV文件路径
 * @return Generator 返回生成器,每次yield一行数据
 * @throws RuntimeException 当文件无法打开时抛出异常
 */
function readCsvFile(string $filePath): Generator {
    $handle = fopen($filePath, 'r');
    if (!$handle) {
        throw new RuntimeException("无法打开文件: $filePath");
    }
    
    try {
        while (($row = fgetcsv($handle)) !== false) {
            yield $row;
        }
    } finally {
        fclose($handle);
    }
}

// 使用示例
foreach (readCsvFile('/path/to/orders.csv') as [$id, $email, $amount]) {
    // 处理每一行数据
}

使用 PDO 预处理语句和事务

php 复制代码
// 数据库连接配置
$dbConfig = [
    'host'      => 'localhost',
    'dbname'    => 'shop',
    'charset'   => 'utf8mb4',
    'username'  => 'username',
    'password'  => 'password'
];

// 创建PDO实例
$dsn = "mysql:host={$dbConfig['host']};dbname={$dbConfig['dbname']};charset={$dbConfig['charset']}";
$pdo = new PDO($dsn, $dbConfig['username'], $dbConfig['password'], [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,  // 设置错误模式为异常
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,        // 设置默认获取模式为关联数组
    PDO::ATTR_EMULATE_PREPARES   => false,                   // 禁用预处理语句的模拟
]);

$pdo->beginTransaction();
try {
    $stmt = $pdo->prepare('INSERT INTO orders (email, amount) VALUES (:email, :amount)');
    
    foreach ($orders as $order) {
        $stmt->execute([
            ':email' => $order['email'],
            ':amount' => $order['amount']
        ]);
    }
    
    $pdo->commit();
} catch (Throwable $e) {
    $pdo->rollBack();
    throw $e;
}

使用 Composer 自动加载

composer.json 中配置:

json 复制代码
{
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
  }
}

运行 composer dump-autoload 使配置生效。

使用属性(PHP 8+)

php 复制代码
#[
    Attribute
] 
class Route {
    public function __construct(
        public string $method, 
        public string $path
    ) {}
}

#[Route('GET', '/health-check')]
function healthCheck(): array {
    return ['status' => '成功'];
}

使用 SPL 迭代器

php 复制代码
$dir = new RecursiveDirectoryIterator(__DIR__ . '/logs');
$iterator = new RecursiveIteratorIterator($dir);

foreach ($iterator as $path => $fileInfo) {
    if ($fileInfo->isFile() && str_ends_with($path, '.log')) {
        // 处理日志文件内容
    }
}

使用特定的异常类型

php 复制代码
/**
 * 订单未找到异常
 */
class OrderNotFoundException extends RuntimeException {}

function getOrder(PDO $db, int $orderId): array {
    $stmt = $db->prepare('SELECT * FROM orders WHERE id = :id');
    $stmt->execute([':id' => $orderId]);
    $row = $stmt->fetch();
    
    if (!$row) {
        throw new OrderNotFoundException("Order with ID $orderId not found");
    }
    
    return $row;
}

创建命令行脚本

php 复制代码
#!/usr/bin/env php
<?php
declare(strict_types=1);

$options = getopt('', ['path:']);
$filePath = $options['path'] ?? 'input.csv';

foreach (readCsvFile($filePath) as $row) {
    // 处理每一行
}

实战示例:CSV 导入数据库

php 复制代码
$db->beginTransaction();
$stmt = $db->prepare('INSERT INTO orders (id, email, amount, created_at) VALUES (:id, :email, :amount, :created_at)');

$batch = 0;

foreach (readCsvFile('orders.csv') as $lineNumber => $row) {
    if ($lineNumber === 0) continue; // 跳过CSV文件的标题行
    
    [$id, $email, $amount, $createdAt] = $row;
    
    // 数据验证
    $email = filter_var($email, FILTER_VALIDATE_EMAIL);
    $amount = is_numeric($amount) ? (float)$amount : null;
    
    if (!$email || $amount === null) {
        // 记录无效数据行
        error_log("第 {$lineNumber} 行数据无效: " . json_encode($row));
        continue;
    }
    
    // 日期时间格式化
    $timezone = new DateTimeZone('Asia/Shanghai');
    $createdAt = (new DateTimeImmutable($createdAt, $timezone))->format('Y-m-d H:i:s');
    
    // 执行数据库插入
    $stmt->execute([
        ':id' => (int)$id,
        ':email' => $email,
        ':amount' => $amount,
        ':created_at' => $createdAt,
    ]);
    
    // 每处理1000条记录提交一次事务
    if ((++$batch % 1000) === 0) {
        $db->commit();
        $db->beginTransaction();
    }
}

$db->commit();

总结

这些技巧可以帮助你:

  1. 编写更健壮的代码
  2. 提高开发效率
  3. 处理大数据量时保持低内存占用
  4. 使代码更易于维护

选择几个最符合你工作流程的技巧开始使用,逐步将它们融入你的日常开发中。

相关推荐
aircrushin9 分钟前
端到端AI决策架构如何重塑实时协作体验?
前端·javascript·后端
苦瓜小生17 分钟前
【黑马点评学习笔记 | 实战篇 】| 6-Redis消息队列
redis·笔记·后端
yhole1 小时前
springboot 修复 Spring Framework 特定条件下目录遍历漏洞(CVE-2024-38819)
spring boot·后端·spring
BingoGo1 小时前
Laravel 13 正式发布 使用 Laravel AI 无缝平滑升级
后端·php
l软件定制开发工作室1 小时前
Spring开发系列教程(34)——打包Spring Boot应用
java·spring boot·后端·spring·springboot
随风,奔跑1 小时前
Spring MVC
java·后端·spring
美团技术团队2 小时前
美团 BI 在指标平台和分析引擎上的探索和实践
后端
JimmtButler2 小时前
我用 Claude Code 给 Claude Code 做了一个 DevTools
后端·claude
Java水解2 小时前
Java 中实现多租户架构:数据隔离策略与实践指南
java·后端
Master_Azur2 小时前
Java面向对象之多态与重写
后端