Skip to content

PHP 标签

PHP 标签是告诉解析器"这里开始是 PHP 代码"和"这里结束 PHP 代码"的特殊标记。理解 PHP 标签的使用方式是编写 PHP 程序的第一步,也是确保代码兼容性和可移植性的基础。

前置知识

  • 了解什么是服务器端脚本语言
  • 基本的 HTML 知识
  • 了解如何配置 PHP 环境(php.ini)

基础概念

当 PHP 解析器处理一个文件时,它会寻找特殊的起始标签和结束标签来界定 PHP 代码的执行范围。在这对标签之外的所有内容都会被原样输出(即直接传给浏览器),而标签之内的内容则会被当作 PHP 代码来解析和执行。

这种机制使得 PHP 可以无缝嵌入到 HTML、XML 以及其他文本文档中,是 PHP 作为模板引擎的基础能力。

四种 PHP 标签风格

PHP 历史上支持四种标签风格:

风格起始标签结束标签推荐程度
标准(XML 兼容)标签<?php?>推荐
短回显标签<?=?>推荐(PHP 5.4+)
短开标签<??>不推荐
ASP 风格标签<%%>已移除(PHP 7.0)

标准标签

标准标签 <?php ... ?> 是最通用、最推荐的 PHP 标签写法。它兼容所有 PHP 配置,并且在 XHTML 和 XML 文档中也能正常工作。

php
<?php
declare(strict_types=1);

// 标准标签是唯一推荐的全功能标签
echo "Hello, World!";
?>

必须在 <?php 后跟随至少一个空白字符(空格、制表符或换行符),否则会导致语法错误:

php
<?php
declare(strict_types=1);

// 正确:标签后有空格
<?php echo "Correct\n"; ?>

// 错误:标签后紧跟非空白字符会导致解析问题
// <?php_echo "Wrong"; ?>

注意事项

在纯 PHP 文件中(即文件只包含 PHP 代码,不包含 HTML),推荐省略结束标签 ?>。这样可以避免文件末尾意外产生的空白字符或换行符,这些空白字符可能在 header() 发送之前导致 "headers already sent" 错误。

php
<?php
declare(strict_types=1);

// 纯 PHP 文件:省略结束标签
class UserService
{
    public function getUserName(int $userId): string
    {
        return "User_{$userId}";
    }
}

// 此处不需要 ?> 结束标签

短回显标签

短回显标签 <?=<?php echo 的简写形式。自 PHP 5.4.0 起,它始终可用,不受 short_open_tag 配置的影响。

php
<?php
declare(strict_types=1);

$name = "PHP";

// 以下两种写法完全等价
<?php echo $name; ?>
<?= $name ?>

短回显标签在模板文件中特别有用,可以大幅减少代码量:

php
<?php
declare(strict_types=1);

$pageTitle = "用户列表";
$userCount = 42;
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title><?= htmlspecialchars($pageTitle, ENT_QUOTES, 'UTF-8') ?></title>
</head>
<body>
    <h1>当前用户数:<?= $userCount ?></h1>
</body>
</html>

版本说明

PHP 5.4.0 起,<?= 短回显标签始终可用,不再需要 short_open_tag = On。这意味着你可以在任何项目中安全地使用 <?= 而不必担心服务器配置。

短开标签

短开标签 <? ... ?> 使用较短的起始标签。它的可用性取决于 php.inishort_open_tag 的配置:

php
<?php
declare(strict_types=1);

// 短开标签的写法
<?
echo "This uses short open tag\n";
?>

强烈不推荐

短开标签 <? 不推荐使用,原因如下:

  1. 它可能被 short_open_tag = Off 禁用
  2. 在 XML/XHTML 文档中可能与 XML 声明 <?xml 冲突
  3. 降低代码的可移植性

配置短开标签

php.ini 中控制短开标签的启用:

ini
; 启用短开标签(不推荐)
short_open_tag = On

; 禁用短开标签(推荐)
short_open_tag = Off

也可以在编译 PHP 时使用 --disable-short-tags 选项来彻底禁用。

ASP 风格标签(已移除)

ASP 风格标签 <% ... %> 模仿了 ASP(Active Server Pages)的语法。该标签风格已在 PHP 7.0.0 中被完全移除

php
<?php
declare(strict_types=1);

// 以下代码在 PHP 7.0+ 中将导致解析错误
// <% echo "ASP style"; %>

// ASP 风格的短回显
// <%= $variable %>

历史背景

ASP 风格标签在 PHP 的早期版本中被引入,目的是方便从 ASP 迁移到 PHP 的开发者。随着 PHP 的发展,这种标签已经不再被需要,最终在 PHP 7.0 中被移除。

详细说明

标签内外的行为差异

理解 PHP 解析器如何处理标签内外的内容非常重要:

  • 标签之外:内容原样输出,PHP 解析器不做任何处理
  • 标签之内:内容作为 PHP 代码解析执行
php
<?php
declare(strict_types=1);

// 这行在 PHP 标签内,会被执行
$greeting = "Hello";

// 下面是标签外的内容,直接输出
?>
<p>这是 HTML 内容,会被原样发送到浏览器。</p>
<?php
// 回到 PHP 标签内,继续执行
echo "<p>{$greeting}, PHP!</p>";
?>

结束标签的隐式行为

结束标签 ?> 隐含了一个分号 ; 和一个换行符。这意味着:

php
<?php
declare(strict_types=1);

// 以下两行等价
echo "Hello"; ?><?php echo "World"
// 等同于
// echo "Hello"; echo "World";

// 结束标签会吃掉紧跟的一个换行符
echo "A"; ?>
B

// 输出:AB(而不是 A\nB)

标签与空白字符

空白字符在 PHP 标签中的处理需要特别注意,尤其是在处理 HTTP 头部时:

php
<?php
declare(strict_types=1);

// 错误示例:文件开头有空行会导致 header() 失败
//
// <?php
// header("Location: /login");
// ?>
// Fatal error: Uncaught Error: Headers already sent

// 正确示例:文件直接以 <?php 开始
<?php
header("Location: /login");
exit;

嵌入不同文档类型

PHP 标签可以嵌入到各种文档类型中:

php
<?php
declare(strict_types=1);

$xmlVersion = "1.0";
$xmlEncoding = "UTF-8";

// 在 XML 中嵌入 PHP(必须使用标准标签)
// 注意:<?xml 声明必须使用 echo 输出
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
?>
<root>
    <message><?= "Hello XML" ?></message>
</root>
php
<?php
declare(strict_types=1);

// 在 CSS 中嵌入 PHP
$themeColor = "#3498db";
?>
<style>
    .primary {
        color: <?= $themeColor ?>;
    }
</style>
php
<?php
declare(strict_types=1);

// 在 JavaScript 中嵌入 PHP
$apiUrl = "/api/v1/users";
$token = "abc123";
?>
<script>
    const API_URL = "<?= $apiUrl ?>";
    const TOKEN = "<?= htmlspecialchars($token, ENT_QUOTES, 'UTF-8') ?>";
</script>

实战示例

模板文件的最佳实践

在实际项目中,模板文件通常混合使用标准标签和短回显标签:

php
<?php
declare(strict_types=1);

// 模板文件 - 数据准备(标准标签)
$title = "商品详情";
$price = 99.99;
$inStock = true;
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title><?= htmlspecialchars($title, ENT_QUOTES, 'UTF-8') ?></title>
</head>
<body>
    <main>
        <h1><?= htmlspecialchars($title) ?></h1>
        <p class="price"><?= number_format($price, 2) ?></p>
        <?php if ($inStock): ?>
            <span class="badge success">有货</span>
        <?php else: ?>
            <span class="badge danger">缺货</span>
        <?php endif; ?>
    </main>
</body>
</html>

多标签切换模式

在模板中频繁进出 PHP 模式是常见且推荐的做法:

php
<?php
declare(strict_types=1);

$users = [
    ["name" => "张三", "role" => "管理员"],
    ["name" => "李四", "role" => "编辑"],
    ["name" => "王五", "role" => "用户"],
];
?>
<table>
    <thead>
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>角色</th>
        </tr>
    </thead>
    <tbody>
        <?php foreach ($users as $index => $user): ?>
        <tr>
            <td><?= $index + 1 ?></td>
            <td><?= htmlspecialchars($user["name"]) ?></td>
            <td><?= htmlspecialchars($user["role"]) ?></td>
        </tr>
        <?php endforeach; ?>
    </tbody>
</table>

纯 PHP 类文件的标准写法

php
<?php
declare(strict_types=1);

namespace App\Services;

use App\Models\User;
use App\Repositories\UserRepository;

/**
 * 用户服务类
 */
class UserService
{
    public function __construct(
        private readonly UserRepository $repository
    ) {
    }

    /**
     * 根据ID获取用户信息
     */
    public function getUserById(int $id): ?User
    {
        return $this->repository->find($id);
    }

    /**
     * 创建新用户
     */
    public function createUser(string $name, string $email): User
    {
        $user = new User($name, $email);
        $this->repository->save($user);

        return $user;
    }

    // 注意:文件末尾没有 ?> 结束标签
}

注意事项

1. <?php 后必须有空格

php
<?php
declare(strict_types=1);

// 正确
<?php echo "OK"; ?>

// 错误 - <?php 后缺少空白字符
// <?phpecho "Error"; ?>

2. 纯 PHP 文件省略结束标签

这是 PSR-12 编码规范的要求,也是 PHP 社区广泛遵循的最佳实践:

php
<?php
declare(strict_types=1);

// PSR-12 规范:纯 PHP 文件省略 ?>
class Example
{
    // ...
}
// 不要在这里写 ?>

3. 短回显标签的安全性

使用短回显标签输出用户数据时,始终要进行转义:

php
<?php
declare(strict_types=1);

$userInput = "<script>alert('XSS')</script>";

// 危险:直接输出
// <?= $userInput ?>

// 安全:转义后输出
<?= htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8') ?>

4. BOM(字节顺序标记)问题

如果 PHP 文件以 UTF-8 BOM (\xEF\xBB\xBF) 开头,会导致 headers already sent 错误。确保编辑器保存文件时不包含 BOM。

5. 各标签的可用性总结

标签风格PHP 版本要求额外配置推荐度
<?php / ?>所有版本必须使用
<?= / ?>PHP 5.4+推荐使用
<? / ?>所有版本(PHP 8 已默认禁用)short_open_tag = On不推荐
<% / %>PHP 3 ~ 7.0asp_tags = On(已移除)不可用

最佳实践

  1. 始终使用标准标签 <?php:这是最安全、最通用的选择
  2. 在模板中使用短回显标签 <?=:减少模板代码量,提高可读性
  3. 纯 PHP 文件省略结束标签:遵循 PSR-12 规范
  4. 避免使用短开标签:降低可移植性,XML 冲突风险
  5. 使用 declare(strict_types=1):启用严格类型检查
  6. 输出外部数据时始终转义:使用 htmlspecialchars() 防止 XSS
  7. 文件使用无 BOM 的 UTF-8 编码:避免隐藏字符问题

下一节

了解了 PHP 标签之后,接下来将学习 PHP 如何从 HTML 中分离,以及如何在 HTML 中嵌入 PHP 代码实现动态内容输出。请阅读 从 HTML 中分离

参考链接