Skip to content

PHP 能做什么

PHP 是一门用途广泛的服务端脚本语言,远不止于「在 HTML 中嵌入动态内容」这一种用途。PHP 可以在三大领域中发挥作用:服务端脚本、命令行脚本以及桌面应用程序开发。本节将全面介绍 PHP 的各种能力,并通过实际代码示例展示如何在不同的应用场景中使用 PHP。

前置知识

阅读本节前,建议你已阅读过 PHP 是什么 一节,了解 PHP 的基本概念和特点。如果你有基本的 Web 开发知识(HTTP 协议、HTML 表单),理解本节内容会更加容易。

基础概念

PHP 的三大应用领域

PHP 官方文档明确指出了 PHP 的三个主要应用领域:

  1. 服务端脚本(Server-side Scripting):这是 PHP 最经典、最广泛的用途。PHP 程序运行在 Web 服务器上,配合 Web 服务器(如 Apache、Nginx)和 PHP 解析器,生成动态网页内容。这种方式需要三个组件:PHP 解析器(CGI 或服务器模块)、Web 服务器和浏览器。

  2. 命令行脚本(Command-line Scripting):PHP 也可以编写无需任何服务器和浏览器参与的命令行脚本。这种方式只需 PHP 解析器即可运行,非常适合编写 cron 任务、日志处理脚本、系统维护工具等。

  3. 桌面应用程序(Desktop Applications):通过 PHP-GTK 扩展,PHP 也可以编写图形界面的桌面应用程序。不过这并非 PHP 的主流用途,社区支持和资源相对有限。

PHP 在现代 Web 开发中的角色

在当今的 Web 开发生态中,PHP 主要承担以下角色:

  • 传统的页面渲染:服务端渲染 HTML 页面
  • API 后端:构建 RESTful / GraphQL / SOAP API
  • 微服务:使用 Swoole / RoadRunner / FrankenPHP 等高性能运行时
  • 队列消费者:处理异步任务队列
  • 定时任务:Cron Job 脚本
  • WebSocket 服务:实时通信服务

语法 — 服务端脚本

最经典的服务端用法

服务端脚本是 PHP 最核心的应用方式。以下示例展示了 PHP 如何在服务器端处理请求并返回动态内容:

php
<?php
declare(strict_types=1);

// server-side-script.php
// 一个简单的服务端脚本,展示动态内容生成

// 设置响应头
header('Content-Type: text/html; charset=UTF-8');

// 处理请求数据
$page = $_GET['page'] ?? 'home';
$userName = $_COOKIE['username'] ?? '访客';
$currentTime = date('Y年m月d日 H:i:s');

// 根据请求参数生成不同的内容
$content = match ($page) {
    'home' => "<h2>欢迎来到首页</h2><p>欢迎你,{$userName}!</p>",
    'about' => '<h2>关于我们</h2><p>这是一个 PHP 演示站点。</p>',
    'contact' => '<h2>联系方式</h2><p>邮箱:hello@example.com</p>',
    default => '<h2>页面未找到</h2><p>请返回首页。</p>',
};
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>PHP 服务端脚本示例</title>
</head>
<body>
    <nav>
        <a href="?page=home">首页</a> |
        <a href="?page=about">关于</a> |
        <a href="?page=contact">联系</a>
    </nav>
    <main>
        <?= $content ?>
        <p>当前时间:<?= $currentTime ?></p>
    </main>
</body>
</html>

构建完整的 Web 页面

PHP 能够生成完整的 HTML 页面,包括处理表单、会话管理、数据库交互等:

php
<?php
declare(strict_types=1);

// complete-page.php — 一个带有访问计数的完整网页示例

session_start();

// 访问计数器
if (!isset($_SESSION['visitCount'])) {
    $_SESSION['visitCount'] = 0;
}
$_SESSION['visitCount']++;

// 收集页面信息
$ipAddress = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
$requestMethod = $_SERVER['REQUEST_METHOD'] ?? 'unknown';
$requestUri = $_SERVER['REQUEST_URI'] ?? '/';

// 判断客户端设备类型
$isMobile = preg_match('/Mobile|Android|iPhone/i', $userAgent);
$deviceType = $isMobile ? '移动设备' : '桌面设备';
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PHP 完整页面示例</title>
</head>
<body>
    <header>
        <h1>PHP 能做什么 演示页面</h1>
    </header>
    <main>
        <section>
            <h2>访问信息</h2>
            <ul>
                <li>IP 地址:<?= htmlspecialchars($ipAddress, ENT_QUOTES, 'UTF-8') ?></li>
                <li>设备类型:<?= $deviceType ?></li>
                <li>请求方法:<?= $requestMethod ?></li>
                <li>请求 URI:<?= htmlspecialchars($requestUri, ENT_QUOTES, 'UTF-8') ?></li>
                <li>会话访问次数:<?= $_SESSION['visitCount'] ?></li>
            </ul>
        </section>
        <section>
            <h2>服务器信息</h2>
            <ul>
                <li>PHP 版本:<?= PHP_VERSION ?></li>
                <li>服务器软件:<?= $_SERVER['SERVER_SOFTWARE'] ?? 'N/A' ?></li>
                <li>服务器时间:<?= date('Y-m-d H:i:s') ?></li>
            </ul>
        </section>
    </main>
</body>
</html>

详细说明

命令行脚本

PHP 在命令行(CLI)模式下有着广泛的应用。CLI 模式的 PHP 不需要 Web 服务器,直接通过操作系统的终端执行。

php
<?php
declare(strict_types=1);

// cli-log-analyzer.php — 日志分析工具
// 用法:php cli-log-analyzer.php /var/log/access.log

if (PHP_SAPI !== 'cli') {
    fwrite(STDERR, "错误:此脚本只能在命令行中运行\n");
    exit(1);
}

// 检查参数
if ($argc < 2) {
    fwrite(STDERR, "用法: php {$argv[0]} <日志文件路径>\n");
    exit(1);
}

$logFile = $argv[1];

if (!file_exists($logFile)) {
    fwrite(STDERR, "错误:日志文件不存在: {$logFile}\n");
    exit(1);
}

// 日志分析
$lines = file($logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$totalRequests = count($lines);
$methodCounts = ['GET' => 0, 'POST' => 0, 'PUT' => 0, 'DELETE' => 0, 'OTHER' => 0];
$statusCodes = [];
$topUrls = [];

foreach ($lines as $line) {
    // 简单的日志解析(以 Apache Combined Log Format 为例)
    if (preg_match('/"(\w+)\s/', $line, $methodMatch)) {
        $method = $methodMatch[1];
        if (isset($methodCounts[$method])) {
            $methodCounts[$method]++;
        } else {
            $methodCounts['OTHER']++;
        }
    }

    // 提取状态码
    if (preg_match('/" (\d{3}) /', $line, $statusMatch)) {
        $code = $statusMatch[1];
        $statusCodes[$code] = ($statusCodes[$code] ?? 0) + 1;
    }

    // 提取 URL
    if (preg_match('/"(\w+)\s([^\s]+)\sHTTP/', $line, $urlMatch)) {
        $url = $urlMatch[2];
        $topUrls[$url] = ($topUrls[$url] ?? 0) + 1;
    }
}

// 输出分析结果
echo "=== 日志分析报告 ===\n";
echo "总请求数: {$totalRequests}\n\n";

echo "--- 请求方法分布 ---\n";
foreach ($methodCounts as $method => $count) {
    $percentage = $totalRequests > 0 ? round(($count / $totalRequests) * 100, 2) : 0;
    echo sprintf("  %-8s %d (%s%%)\n", $method, $count, $percentage);
}

echo "\n--- 状态码分布 ---\n";
arsort($statusCodes);
foreach ($statusCodes as $code => $count) {
    echo "  {$code}: {$count}\n";
}

echo "\n--- Top 10 热门 URL ---\n";
arsort($topUrls);
$top10 = array_slice($topUrls, 0, 10, true);
foreach ($top10 as $url => $count) {
    echo "  [{$count}] {$url}\n";
}

CLI 专属功能

PHP 的 CLI SAPI 提供了一些 Web 模式下不可用的常量和流:

  • STDINSTDOUTSTDERR:标准输入/输出/错误流
  • $argv:命令行参数数组
  • $argc:参数个数
  • getopt():解析命令行选项

Web 服务端 — 构建 RESTful API

PHP 常用于构建 Web API。以下是一个简单的 RESTful API 示例:

php
<?php
declare(strict_types=1);

// api-router.php — 一个简单的 RESTful API 路由器

header('Content-Type: application/json; charset=UTF-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');

// 处理 OPTIONS 预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

// 简单的路由系统
$requestMethod = $_SERVER['REQUEST_METHOD'];
$requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$pathSegments = explode('/', trim($requestUri, '/'));

// 模拟数据库
$users = [
    1 => ['id' => 1, 'name' => '张三', 'email' => 'zhangsan@example.com'],
    2 => ['id' => 2, 'name' => '李四', 'email' => 'lisi@example.com'],
    3 => ['id' => 3, 'name' => '王五', 'email' => 'wangwu@example.com'],
];

$nextId = 4;

// 路由分发
try {
    $resource = $pathSegments[0] ?? '';
    $id = $pathSegments[1] ?? null;

    if ($resource !== 'users') {
        http_response_code(404);
        echo json_encode(['error' => '资源未找到']);
        exit;
    }

    match ($requestMethod) {
        'GET' => $id ? handleGetUser($users, (int) $id) : handleGetUsers($users),
        'POST' => handleCreateUser($users, $nextId),
        'PUT' => $id ? handleUpdateUser($users, (int) $id) : throw new Exception('缺少用户 ID', 400),
        'DELETE' => $id ? handleDeleteUser($users, (int) $id) : throw new Exception('缺少用户 ID', 400),
        default => throw new Exception('不支持的请求方法', 405),
    };
} catch (Exception $e) {
    http_response_code($e->getCode() ?: 500);
    echo json_encode(['error' => $e->getMessage()]);
}

function handleGetUsers(array $users): void
{
    echo json_encode(['data' => array_values($users), 'count' => count($users)]);
}

function handleGetUser(array $users, int $id): void
{
    if (!isset($users[$id])) {
        http_response_code(404);
        echo json_encode(['error' => '用户不存在']);
        return;
    }
    echo json_encode(['data' => $users[$id]]);
}

function handleCreateUser(array &$users, int $nextId): void
{
    $input = json_decode(file_get_contents('php://input'), true);
    if (empty($input['name']) || empty($input['email'])) {
        http_response_code(422);
        echo json_encode(['error' => '缺少必要字段:name 和 email']);
        return;
    }
    $newUser = ['id' => $nextId, 'name' => $input['name'], 'email' => $input['email']];
    http_response_code(201);
    echo json_encode(['data' => $newUser]);
}

function handleUpdateUser(array &$users, int $id): void
{
    if (!isset($users[$id])) {
        http_response_code(404);
        echo json_encode(['error' => '用户不存在']);
        return;
    }
    $input = json_decode(file_get_contents('php://input'), true);
    $users[$id]['name'] = $input['name'] ?? $users[$id]['name'];
    $users[$id]['email'] = $input['email'] ?? $users[$id]['email'];
    echo json_encode(['data' => $users[$id]]);
}

function handleDeleteUser(array &$users, int $id): void
{
    if (!isset($users[$id])) {
        http_response_code(404);
        echo json_encode(['error' => '用户不存在']);
        return;
    }
    $deleted = $users[$id];
    unset($users[$id]);
    echo json_encode(['data' => $deleted, 'message' => '用户已删除']);
}

生产环境建议

以上 API 路由器仅用于教学演示。在实际项目中,你应该使用成熟的 PHP 框架(如 Laravel、Symfony、Slim)来构建 API,它们提供了完善的路由、中间件、验证和错误处理机制。

PHP-GTK 桌面应用

PHP-GTK 是 PHP 的一个扩展,允许开发者使用 GTK+ 库来编写图形用户界面应用程序。虽然这不是 PHP 的主流用途,但在某些特定场景下有其价值:

php
<?php
declare(strict_types=1);

// 注意:PHP-GTK 需要单独安装
// 本示例仅作概念性展示,展示 PHP 在桌面应用领域的可能性

// PHP-GTK 的基本概念示例(伪代码)
// if (!class_exists('GtkWindow')) {
//     echo "PHP-GTK 未安装。\n";
//     echo "请参考 https://gtk.php.net/ 了解安装方法。\n";
//     exit(1);
// }
//
// $window = new GtkWindow();
// $window->setTitle('PHP Desktop App');
// $window->setSizeRequest(400, 300);
// $window->connectSimple('destroy', ['Gtk', 'main_quit']);
//
// $label = new GtkLabel('Hello from PHP-GTK!');
// $window->add($label);
//
// $window->showAll();
// Gtk::main();

echo "PHP-GTK 允许 PHP 编写桌面应用,但生态相对较小。\n";
echo "推荐使用以下工具替代:\n";
echo "  - Electron (JavaScript) — 跨平台桌面应用\n";
echo "  - Tauri (Rust + Web) — 轻量跨平台桌面应用\n";
echo "  - PyQt (Python) — 功能丰富的桌面应用\n";

PHP 在不同领域的应用实例

内容管理系统(CMS)

PHP 是 CMS 领域的绝对霸主。全球最知名的内容管理系统几乎都是用 PHP 编写的:

CMS市场占有率特点
WordPress~43%全球最流行的 CMS,插件生态极其丰富
Shopware电子商务德国的专业电商 CMS
Drupal~1.5%企业级 CMS,高度可定制
Joomla~2%中型站点 CMS,介于 WordPress 和 Drupal 之间

电子商务

PHP 在电子商务领域同样占据重要地位:

php
<?php
declare(strict_types=1);

// 一个简单的商品价格计算器示例
class PriceCalculator
{
    public function __construct(
        private readonly float $taxRate = 0.13, // 13% 增值税
        private readonly string $currency = 'CNY'
    ) {
    }

    public function calculate(
        float $unitPrice,
        int $quantity,
        float $discountRate = 0.0
    ): array {
        $subtotal = $unitPrice * $quantity;
        $discountAmount = $subtotal * $discountRate;
        $afterDiscount = $subtotal - $discountAmount;
        $tax = $afterDiscount * $this->taxRate;
        $total = $afterDiscount + $tax;

        return [
            'unit_price' => round($unitPrice, 2),
            'quantity' => $quantity,
            'subtotal' => round($subtotal, 2),
            'discount_rate' => $discountRate,
            'discount_amount' => round($discountAmount, 2),
            'tax_rate' => $this->taxRate,
            'tax_amount' => round($tax, 2),
            'total' => round($total, 2),
            'currency' => $this->currency,
            'formatted_total' => "¥" . number_format($total, 2),
        ];
    }
}

// 使用示例
$calculator = new PriceCalculator(taxRate: 0.13);

// 计算一件商品,单价 299 元,购买 3 件,打 85 折
$result = $calculator->calculate(
    unitPrice: 299.00,
    quantity: 3,
    discountRate: 0.15
);

echo "=== 购物明细 ===\n";
echo "单价:¥{$result['unit_price']} x {$result['quantity']}\n";
echo "小计:¥{$result['subtotal']}\n";
echo "折扣:{$result['discount_rate'] * 100}% (减免 ¥{$result['discount_amount']})\n";
echo "税费({$result['tax_rate'] * 100}%):¥{$result['tax_amount']}\n";
echo "合计:{$result['formatted_total']}\n";

图像处理

PHP 通过 GD 扩展或 Imagick 扩展提供了强大的图像处理能力:

php
<?php
declare(strict_types=1);

// image-processor.php — 图像处理示例
// 需要 GD 扩展(extension=gd)

if (!extension_loaded('gd')) {
    echo "GD 扩展未加载,无法进行图像处理。\n";
    exit(1);
}

/**
 * 生成一个带文字水印的缩略图
 */
function createThumbnailWithWatermark(
    string $sourcePath,
    string $outputPath,
    int $maxWidth = 200,
    int $maxHeight = 200,
    string $watermarkText = 'PHP Demo'
): bool {
    // 获取原始图像信息
    $imageInfo = getimagesize($sourcePath);
    if ($imageInfo === false) {
        return false;
    }

    // 创建图像资源
    [$srcWidth, $srcHeight, $type] = $imageInfo;

    match ($type) {
        IMAGETYPE_JPEG => $sourceImage = imagecreatefromjpeg($sourcePath),
        IMAGETYPE_PNG => $sourceImage = imagecreatefrompng($sourcePath),
        IMAGETYPE_GIF => $sourceImage = imagecreatefromgif($sourcePath),
        IMAGETYPE_WEBP => $sourceImage = imagecreatefromwebp($sourcePath),
        default => throw new RuntimeException("不支持的图像类型: {$type}"),
    };

    // 计算缩略图尺寸(等比缩放)
    $ratio = min($maxWidth / $srcWidth, $maxHeight / $srcHeight);
    $thumbWidth = (int) ($srcWidth * $ratio);
    $thumbHeight = (int) ($srcHeight * $ratio);

    // 创建缩略图
    $thumbnail = imagecreatetruecolor($thumbWidth, $thumbHeight);
    imagecopyresampled($thumbnail, $sourceImage, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $srcWidth, $srcHeight);

    // 添加水印
    $white = imagecolorallocatealpha($thumbnail, 255, 255, 255, 80);
    $font = 3; // 内置字体大小
    $textWidth = imagefontwidth($font) * strlen($watermarkText);
    $textHeight = imagefontheight($font);
    $x = ($thumbWidth - $textWidth) / 2;
    $y = $thumbHeight - $textHeight - 10;
    imagestring($thumbnail, $font, (int) $x, (int) $y, $watermarkText, $white);

    // 保存缩略图
    $result = imagejpeg($thumbnail, $outputPath, 85);

    // 释放资源
    imagedestroy($sourceImage);
    imagedestroy($thumbnail);

    return $result;
}

echo "图像处理功能就绪\n";
echo "支持的图像类型:JPEG, PNG, GIF, WebP\n";

邮件发送

PHP 可以通过内置的 mail() 函数或第三方库(如 PHPMailer、Symfony Mailer)发送邮件:

php
<?php
declare(strict_types=1);

// email-service.php — 使用 PHPMailer 发送邮件的示例
// 注意:需要通过 Composer 安装 phpmailer/phpmailer

namespace App\Services;

/**
 * 邮件服务类
 *
 * 使用示例:
 *   $mailer = new EmailService(
 *       smtpHost: 'smtp.example.com',
 *       smtpPort: 465,
 *       smtpUser: 'noreply@example.com',
 *       smtpPass: 'password'
 *   );
 *   $mailer->send('recipient@example.com', '测试邮件', '<h1>Hello</h1>');
 */
class EmailService
{
    private bool $isConfigured = false;

    public function __construct(
        private readonly ?string $smtpHost = null,
        private readonly int $smtpPort = 587,
        private readonly ?string $smtpUser = null,
        private readonly ?string $smtpPass = null,
        private readonly string $encryption = 'tls'
    ) {
        if ($this->smtpHost && $this->smtpUser && $this->smtpPass) {
            $this->isConfigured = true;
        }
    }

    public function send(
        string $to,
        string $subject,
        string $body,
        bool $isHtml = true,
        string $fromName = 'PHP Demo'
    ): bool {
        if (!$this->isConfigured) {
            throw new \RuntimeException('SMTP 未配置');
        }

        // 这里使用 PHPMailer 的实际代码
        // 实际项目中请安装 phpmailer/phpmailer
        echo "邮件发送配置就绪\n";
        echo "收件人:{$to}\n";
        echo "主题:{$subject}\n";
        echo "正文类型:" . ($isHtml ? 'HTML' : '纯文本') . "\n";

        return true;
    }

    public function isConfigured(): bool
    {
        return $this->isConfigured;
    }
}

文件操作

PHP 提供了非常丰富的文件系统操作函数:

php
<?php
declare(strict_types=1);

// file-manager.php — 文件和目录操作示例

class FileManager
{
    /**
     * 递归列出目录内容
     */
    public function listDirectory(string $dirPath, bool $recursive = false): array
    {
        $result = [];
        $items = scandir($dirPath);

        foreach ($items as $item) {
            if ($item === '.' || $item === '..') {
                continue;
            }

            $fullPath = $dirPath . DIRECTORY_SEPARATOR . $item;
            $isDir = is_dir($fullPath);

            $result[] = [
                'name' => $item,
                'path' => $fullPath,
                'type' => $isDir ? 'directory' : 'file',
                'size' => $isDir ? 0 : filesize($fullPath),
                'modified' => filemtime($fullPath),
            ];

            if ($recursive && $isDir) {
                $subItems = $this->listDirectory($fullPath, true);
                $result = array_merge($result, $subItems);
            }
        }

        return $result;
    }

    /**
     * 安全地写入文件(自动创建目录)
     */
    public function writeFile(string $filePath, string $content, int $flags = 0): bool
    {
        $dir = dirname($filePath);

        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }

        $bytesWritten = file_put_contents($filePath, $content, $flags);
        return $bytesWritten !== false;
    }

    /**
     * 读取 CSV 文件
     */
    public function readCsv(string $filePath, string $delimiter = ','): array
    {
        if (!file_exists($filePath)) {
            throw new RuntimeException("文件不存在: {$filePath}");
        }

        $handle = fopen($filePath, 'r');
        $headers = fgetcsv($handle, 0, $delimiter);
        $rows = [];

        while (($row = fgetcsv($handle, 0, $delimiter)) !== false) {
            if (count($row) === count($headers)) {
                $rows[] = array_combine($headers, $row);
            }
        }

        fclose($handle);
        return $rows;
    }
}

// 使用示例
$manager = new FileManager();

echo "=== 文件管理器演示 ===\n";

// 写入文件
$manager->writeFile('/tmp/php-demo/test.txt', "Hello from PHP!\n这是测试文件。\n");
echo "文件写入完成\n";

// 读取文件
$content = file_get_contents('/tmp/php-demo/test.txt');
echo "文件内容:{$content}";

实战示例

多用途 PHP 工具类

以下是一个展示了 PHP 多种能力的综合示例:

php
<?php
declare(strict_types=1);

/**
 * PHP 多用途工具类
 * 展示 PHP 在不同场景下的能力
 */

final class PhpToolkit
{
    // ========== 网络功能 ==========
    public static function fetchUrl(string $url, int $timeout = 30): string
    {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => $timeout,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_USERAGENT => 'PHP-Toolkit/1.0',
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($response === false) {
            throw new RuntimeException("请求失败: {$error}");
        }

        if ($httpCode >= 400) {
            throw new RuntimeException("HTTP 错误: {$httpCode}");
        }

        return $response;
    }

    // ========== 数据处理 ==========
    public static function arrayToXml(array $data, string $rootTag = 'root'): string
    {
        $xml = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"UTF-8\"?><{$rootTag}/>");

        self::arrayToXmlRecursive($data, $xml);
        return $xml->asXML();
    }

    private static function arrayToXmlRecursive(array $data, SimpleXMLElement $xml): void
    {
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                $subNode = $xml->addChild(is_numeric($key) ? 'item' : $key);
                self::arrayToXmlRecursive($value, $subNode);
            } else {
                $xml->addChild(is_numeric($key) ? 'item' : $key, htmlspecialchars((string) $value));
            }
        }
    }

    // ========== 加密功能 ==========
    public static function encrypt(string $data, string $key): string
    {
        $iv = random_bytes(openssl_cipher_iv_length('aes-256-cbc'));
        $encrypted = openssl_encrypt($data, 'aes-256-cbc', hash('sha256', $key), OPENSSL_RAW_DATA, $iv);
        return base64_encode($iv . $encrypted);
    }

    public static function decrypt(string $data, string $key): string
    {
        $decoded = base64_decode($data);
        $ivLength = openssl_cipher_iv_length('aes-256-cbc');
        $iv = substr($decoded, 0, $ivLength);
        $encrypted = substr($decoded, $ivLength);
        $decrypted = openssl_decrypt($encrypted, 'aes-256-cbc', hash('sha256', $key), OPENSSL_RAW_DATA, $iv);

        if ($decrypted === false) {
            throw new RuntimeException('解密失败');
        }

        return $decrypted;
    }

    // ========== 字符串工具 ==========
    public static function generateSlug(string $text, string $separator = '-'): string
    {
        // 移除特殊字符,转为 ASCII
        $text = transliterator_transliterate('Any-Latin; Latin-ASCII; Lower()', $text);
        $text = preg_replace('/[^a-z0-9]+/i', $separator, $text);
        return trim($text, $separator);
    }

    public static function generateRandomString(int $length = 32): string
    {
        $bytes = random_bytes(ceil($length / 2));
        return substr(bin2hex($bytes), 0, $length);
    }
}

// 演示
echo "=== PHP 工具类演示 ===\n\n";

// 1. 字符串工具
echo "--- 字符串工具 ---\n";
echo "Slug 生成: " . PhpToolkit::generateSlug('PHP 能做什么?') . "\n";
echo "随机字符串: " . PhpToolkit::generateRandomString(16) . "\n\n";

// 2. 数据转换
echo "--- 数据转换 ---\n";
$data = ['user' => ['name' => '张三', 'age' => 30, 'email' => 'zhangsan@example.com']];
$xml = PhpToolkit::arrayToXml($data, 'user-info');
echo "数组转 XML:\n{$xml}\n\n";

// 3. 加密解密
echo "--- 加密解密 ---\n";
$secret = '这是一条秘密信息';
$key = 'my-secret-key-12345';
$encrypted = PhpToolkit::encrypt($secret, $key);
$decrypted = PhpToolkit::decrypt($encrypted, $key);
echo "原文: {$secret}\n";
echo "加密: {$encrypted}\n";
echo "解密: {$decrypted}\n";

注意事项

  • 选择正确的运行模式:根据你的用途选择适当的 PHP 运行模式(Web 服务端 / CLI / 内置服务器)。开发时可以使用 php -S localhost:8000 启动内置服务器。
  • 资源限制:PHP 在 Web 模式下受到 php.ini 中的 max_execution_timememory_limit 等配置的限制,处理长时间任务时应使用 CLI 模式或队列系统。
  • 安全第一:处理用户输入时,始终使用 htmlspecialchars() 对输出进行转义,使用预处理语句防止 SQL 注入。
  • 扩展检查:使用 PHP 的某些功能前,先用 extension_loaded() 检查所需的扩展是否已启用。
  • CLI 与 Web 的区别:CLI 模式下没有 $_GET$_POST 等超全局变量,也不受 max_execution_time 默认值的限制。

最佳实践

  • 使用 PHP 内置服务器 php -S localhost:8000 进行本地开发和测试。
  • CLI 脚本使用 #!/usr/bin/env php 作为 shebang 行,方便直接执行。
  • 为 CLI 脚本提供 --help 参数和友好的错误信息。
  • 构建正式 API 时使用成熟的框架(Laravel、Symfony),而不是手写路由系统。
  • 使用 PHPMailer 或 Symfony Mailer 发送邮件,而不是 mail() 函数。
  • 图像处理时考虑使用 Imagick 扩展(功能更强)或 Intervention Image 库。
  • 文件操作始终检查文件是否存在、是否有读写权限。
  • 使用 Composer 管理第三方库,避免重复造轮子。

下一节

了解了 PHP 的各种能力之后,让我们来看看 PHP 的发展历史与版本演变,理解 PHP 是如何一步步发展到今天的。

参考链接