当前位置:编程学习 > php >>

2025 年 PHP8 开发者必看 推荐的代码写法

php8开发几个要点:

• 用严格类型,给函数加上类型声明
• PHP 8 的新特性很好用,别浪费了
• 安全问题不能马虎,SQL 注入、密码存储都要注意
• 性能优化要有针对性,别过早优化
• 代码要写得清晰,别人能看懂
• SOLID 原则还是很有用的
• 错误处理要到位,别让程序莫名其妙挂掉
• 日志要记得详细点,出问题好排查
• 代码要能测试,不然改起来心里没底

• PHP 更新很快,要跟上节奏


很多老旧写法及时换成php8新写法

如果还需要兼容低版本php需要注意!(代码本身没有错误,只是php8新写法效率更好,代码更优雅


用 == 比较,结果不符合预期
// 不推荐
function isUserActive($status) {
    if ($status == true) {  // '1', 1, true, 'true' 都会被判断为 true
        return true;
    }
    return false;
}

// 正确做法
function isUserActive(bool $status): bool {
    return $status === true;
}
直接访问数组元素,没检查是否存在
// 不推荐
function getUserName($user) {
    return $user['name'];  // name 不存在就报错了
}

// 正确做法
function getUserName(array $user): string {
    return $user['name'] ?? 'Unknown';  // 用 ?? 操作符兜底
}
在循环里拼接字符串,性能很差
// 不推荐
function buildReport(array $items): string {
    $report = '';
    foreach ($items as $item) {
        $report = $report . $item->description;  // 每次都创建新字符串
    }
    return $report;
}

// 正确做法
function buildReport(array $items): string {
    $reports = [];
    foreach ($items as $item) {
        $reports[] = $item->description;
    }
    return implode('', $reports);
}
SQL 语句直接拼接参数,有注入风险
// 不推荐
function findUser($db, $userId) {
    return $db->query("SELECT * FROM users WHERE id = " . $userId);  // 这样写有 SQL 注入风险
}

// 正确做法
function findUser(PDO $db, int $userId): ?array {
    $stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
    $stmt->execute([$userId]);
    return $stmt->fetch(PDO::FETCH_ASSOC);
}
读取文件时不做错误处理
// 不推荐
function readConfig($filename) {
    $content = file_get_contents($filename);  // 文件不存在或读取失败怎么办?
    return json_decode($content);
}

// 正确做法
function readConfig(string $filename): array {
    if (!file_exists($filename)) {
        throw new RuntimeException("文件不存在: $filename");
    }

    $content = file_get_contents($filename);
    if ($content === false) {
        throw new RuntimeException("读取文件失败: $filename");
    }

    $data = json_decode($content, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new RuntimeException("JSON 格式有问题: " . json_last_error_msg());
    }

    return $data;
}
函数参数和返回值不声明类型
// 不推荐
function calculateTotal($price, $quantity) {
    return $price * $quantity;
}

// 正确做法
function calculateTotal(float $price, int $quantity): float {
    return $price * $quantity;
}
用 @ 符号屏蔽错误,问题难排查
// 不推荐
function getImageSize($filename) {
    return @getimagesize($filename);  // 静默抑制错误
}

// 正确做法
function getImageSize(string $filename): ?array {
    if (!file_exists($filename)) {
        return null;
    }

    $size = getimagesize($filename);
    return $size !== false ? $size : null;
}
不用命名空间,污染全局环境
// 不推荐 - 污染全局命名空间
class User {}
class Order {}

// 正确做法
namespace App\Models;
class User {}

namespace App\Orders;
class Order {}
捕获异常时太笼统,不区分类型
// 不推荐
function processOrder($order) {
    try {
        // 处理订单
    } catch (Exception $e) {
        error_log($e->getMessage());  // 通用的异常捕获
    }
}

// 正确做法
function processOrder(Order $order): void {
    try {
        // 处理订单
    } catch (DatabaseException $e) {
        // 处理数据库相关错误
        throw new OrderProcessingException("处理订单时数据库错误", 0, $e);
    } catch (ValidationException $e) {
        // 处理验证相关错误
        throw new OrderProcessingException("订单验证失败", 0, $e);
    }
}
没用 PHP 8 的构造器属性提升
// 不推荐
class Customer {
    private string $name;
    private string $email;

    public function __construct(string $name, string $email) {
        $this->name = $name;
        $this->email = $email;
    }
}

// 正确做法
class Customer {
    public function __construct(
        private string $name,
        private string $email,
    ) {}
}
不用 PHP 8 的空安全操作符 ?->
// 不推荐
function getCountryName($user) {
    if ($user !== null &&
        $user->getAddress() !== null &&
        $user->getAddress()->getCountry() !== null) {
        return $user->getAddress()->getCountry()->getName();
    }
    return null;
}

// 正确做法
function getCountryName(?User $user): ?string {
    return $user?->getAddress()?->getCountry()?->getName();
}
数组操作不够高效
// 不推荐
function findUser(array $users, string $email): ?array {
    foreach ($users as $user) {
        if ($user['email'] === $email) {
            return $user;
        }
    }
    return null;
}

// 正确做法
function findUser(array $users, string $email): ?array {
    return array_filter(
        $users,
        fn($user) => $user['email'] === $email
    )[0] ?? null;
}
不用数组解构,代码冗余
// 不推荐
function processCoordinates($point) {
    $x = $point[0];
    $y = $point[1];
    return sqrt($x * $x + $y * $y);
}

// 正确做法
function processCoordinates(array $point): float {
    [$x, $y] = $point;
    return sqrt($x * $x + $y * $y);
}
日期处理用时间戳,不用 DateTime
// 不推荐
function isUserActive($lastLoginTimestamp) {
    return (time() - $lastLoginTimestamp) < (30 * 24 * 60 * 60);
}

// 正确做法
function isUserActive(DateTime $lastLogin): bool {
    $thirtyDaysAgo = new DateTime('-30 days');
    return $lastLogin > $thirtyDaysAgo;
}
还在用 switch,不用 PHP 8 的 match
// 不推荐
function getStatusMessage($status) {
    switch ($status) {
        case 'pending':
            return '订单待处理';
        case 'processing':
            return '订单处理中';
        case 'completed':
            return '订单已完成';
        default:
            return '未知状态';
    }
}

// 正确做法
function getStatusMessage(string $status): string {
    return match($status) {
        'pending' => '订单待处理',
        'processing' => '订单处理中',
        'completed' => '订单已完成',
        default => '未知状态',
    };
}
不用 PHP 8 的命名参数
// 不推荐
function createUser($name, $email, $age = null, $country = null) {
    // 必须记住参数顺序
    return new User($name, $email, null, 'US');
}

// 正确做法
function createUser(
    string $name,
    string $email,
    ?int $age = null,
    ?string $country = null
): User {
    return new User(
        name: $name,
        email: $email,
        age: $age,
        country: $country ?? 'US'
    );
}
验证邮箱等数据时方法不对
// 不推荐
function validateEmail($email) {
    return strpos($email, '@') !== false;
}

// 正确做法
function validateEmail(string $email): bool {
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
处理大文件时一次性读入内存
// 不推荐
function processLargeFile($filename) {
    $content = file_get_contents($filename); // 将整个文件加载到内存
    $lines = explode("\n", $content);
    foreach ($lines as $line) {
        // 处理每行
    }
}

// 正确做法
function processLargeFile(string $filename): void {
    $handle = fopen($filename, 'r');
    while (($line = fgets($handle)) !== false) {
        // 处理每行
    }
    fclose($handle);
}
在类里直接 new 对象,不用依赖注入
// 不推荐
class UserService {
    private $db;

    public function __construct() {
        $this->db = new Database(); // 硬编码依赖
    }
}

// 正确做法
class UserService {
    public function __construct(
        private readonly DatabaseInterface $db
    ) {}
}
自定义异常不定义错误码
// 不推荐
class CustomException extends Exception {
    public function __construct($message) {
        parent::__construct($message);
    }
}

// 正确做法
class CustomException extends Exception {
    public const INVALID_INPUT = 1001;
    public const DATABASE_ERROR = 1002;
    public const API_ERROR = 1003;

    public function __construct(
        string $message,
        int $code = self::INVALID_INPUT,
        ?Throwable $previous = null
    ) {
        parent::__construct($message, $code, $previous);
    }
}
不用提前返回,嵌套太深
// 不推荐
function processUser($user) {
    if ($user !== null) {
        if ($user->isActive()) {
            if ($user->hasPermission('admin')) {
                // 执行操作
                return true;
            }
        }
    }
    return false;
}

// 正确做法
function processUser(?User $user): bool {
    if ($user === null) {
        return false;
    }

    if (!$user->isActive()) {
        return false;
    }

    if (!$user->hasPermission('admin')) {
        return false;
    }

    // 执行操作
    return true;
}
数组初始化为 null,后面可能出错
// 不推荐
$items = null;
if (someCondition()) {
    $items = [];
}

// 正确做法
$items = [];
if (someCondition()) {
    // 填充数组
}
日志记录信息不够详细
// 不推荐
function processPayment($amount) {
    try {
        // 处理支付
    } catch (Exception $e) {
        error_log('支付失败');
    }
}

// 正确做法
function processPayment(float $amount): void {
    try {
        // 处理支付
    } catch (PaymentException $e) {
        $context = [
            'amount' => $amount,
            'error' => $e->getMessage(),
            'trace' => $e->getTraceAsString(),
            'timestamp' => date('Y-m-d H:i:s')
        ];
        $this->logger->error('支付处理失败', $context);
        throw $e;
    }
}
不用服务容器,手动管理依赖
// 不推荐
class UserController {
    private UserService $userService;
    private Logger $logger;

    public function __construct() {
        $this->userService = new UserService(new Database());
        $this->logger = new Logger();
    }
}

// 正确做法
class Container {
    private array $services = [];
    private array $factories = [];

    public function register(string $id, callable $factory): void {
        $this->factories[$id] = $factory;
    }

    public function get(string $id): object {
        if (!isset($this->services[$id])) {
            if (!isset($this->factories[$id])) {
                throw new ServiceNotFoundException($id);
            }
            $this->services[$id] = $this->factories[$id]();
        }

        return $this->services[$id];
    }
}

class UserController {
    public function __construct(
        private readonly UserService $userService,
        private readonly LoggerInterface $logger
    ) {}
}
用 MD5 等弱算法存储密码
// 不推荐
function setPassword($password) {
    $this->password = md5($password); // 绝不要用 MD5 处理密码
}

// 正确做法
function setPassword(string $password): void {
    $this->password = password_hash(
        $password,
        PASSWORD_DEFAULT,
        ['cost' => 12]
    );
}

CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,