概览
PHP
PHP(Hypertext Preprocessor)是广泛使用的开源服务器端脚本语言,由 Rasmus Lerdorf 于 1994 年创建。专为 Web 开发设计,可嵌入 HTML 中执行。支撑了全球约 75% 的网站(含 WordPress、Facebook 早期版本)。核心特性:动态弱类型、丰富的内置函数库、C 风格语法、跨平台部署、出色的数据库集成能力。
PHP(Hypertext Preprocessor)是广泛使用的开源服务器端脚本语言,由 Rasmus Lerdorf 于 1994 年创建。专为 Web 开发设计,可嵌入 HTML 中执行。支撑了全球约 75% 的网站(含 WordPress、Facebook 早期版本)。核心特性:动态弱类型、丰富的内置函数库、C 风格语法、跨平台部署、出色的数据库集成能力。
# 添加 PPA(获取最新版本)
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
# 安装 PHP 8.3 + 常用扩展
sudo apt install -y php8.3 php8.3-cli php8.3-fpm php8.3-mbstring \
php8.3-xml php8.3-curl php8.3-mysql php8.3-sqlite3 \
php8.3-zip php8.3-gd php8.3-intl php8.3-bcmath
# 验证
php -v
brew install php@8.3
# 扩展
brew install php@8.3-mbstring php@8.3-xml php@8.3-curl
推荐两种方式:
docker run -d -p 8080:80 --name my-php-app \
-v "$PWD":/var/www/html php:8.3-apache
缺少编译依赖。Ubuntu 下运行:
sudo apt build-dep php
检查 php.ini 位置:
php --ini
确保 extension=mbstring(等行)未被注释。
php-fpm 用户对项目目录有读权限chcon -R -t httpd_sys_content_t /var/www/html# Ubuntu
sudo update-alternatives --config php
# macOS
brew unlink php@8.2 && brew link php@8.3 --force
运行第一个 PHP 程序:输出 "Hello, World!" 并在浏览器中验证。
创建 hello.php:
<?php
echo "Hello, World!\n";
echo "今天的日期是:" . date('Y-m-d') . "\n";
运行:
php hello.php
预期输出:
Hello, World!
今天的日期是:2026-01-15
在同一目录运行:
php -S localhost:8000
浏览器访问 http://localhost:8000/hello.php,页面显示:
Hello, World!
今天的日期是:2026-01-15
创建 index.php:
<!DOCTYPE html>
<html>
<head><title>PHP Hello World</title></head>
<body>
<h1><?php echo "Hello, World!"; ?></h1>
<p>服务器时间:<?php echo date('H:i:s'); ?></p>
<p>PHP 版本:<?php echo phpversion(); ?></p>
</body>
</html>
<?php ... ?> 是 PHP 代码块标记,可嵌入 HTML 任意位置echo 是最常用的输出语句; 结尾.phpPHP 最初代表 "Personal Home Page"(Rasmus Lerdorf,1994),后来演变为 "PHP: Hypertext Preprocessor"。它设计之初就是为了让开发者在 HTML 里嵌入动态逻辑。
<?php
$name = "Vibe"; // 字符串
$count = 42; // 整数
$price = 19.99; // 浮点数
$isAdmin = true; // 布尔
$items = ["A", "B", "C"]; // 数组
$user = null; // null
// 类型检查
var_dump($count); // int(42)
echo gettype($price); // double
// 双引号解析变量
echo "Hello, $name!"; // Hello, Vibe!
// 连接符 .(不是 +)
echo "Hello, " . $name;
// Heredoc(多行)
$html = <<<HTML
<div>
<p>Welcome, $name</p>
</div>
HTML;
// 索引数组
$colors = ["red", "green", "blue"];
// 关联数组(相当于字典)
$user = [
"name" => "Alice",
"email" => "alice@example.com",
];
// 遍历
foreach ($user as $key => $value) {
echo "$key: $value\n";
}
// 实用函数
count($colors); // 3
in_array("red", $colors); // true
array_merge([1,2], [3,4]);// [1,2,3,4]
function greet(string $name, string $title = "Mr."): string
{
return "Hello, $title $name!";
}
echo greet("Smith"); // Hello, Mr. Smith!
echo greet("Jane", "Ms."); // Hello, Ms. Jane!
// 箭头函数(PHP 7.4+)
$double = fn($x) => $x * 2;
echo $double(5); // 10
// URL: /search.php?q=php&page=1
$query = $_GET['q'] ?? 'default';
$page = (int)($_GET['page'] ?? 1);
echo "搜索: $query, 第 $page 页";
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = htmlspecialchars($_POST['name'] ?? '');
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);
if ($email === false) {
die("无效的 Email");
}
echo "已接收: $name ($email)";
}
if (isset($_FILES['avatar']) && $_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
$tmpPath = $_FILES['avatar']['tmp_name'];
$destPath = 'uploads/' . basename($_FILES['avatar']['name']);
move_uploaded_file($tmpPath, $destPath);
echo "文件已保存至 $destPath";
}
$pdo = new PDO('mysql:host=localhost;dbname=app;charset=utf8mb4', 'root', '');
// 查询(防 SQL 注入 — 预处理)
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => 1]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
// 插入
$stmt = $pdo->prepare('INSERT INTO posts (title, body) VALUES (:title, :body)');
$stmt->execute([
'title' => 'Hello PHP',
'body' => 'This is my first post.',
]);
echo "新纪录 ID: " . $pdo->lastInsertId();
session_start();
// 登录
$_SESSION['user_id'] = 42;
$_SESSION['username'] = 'alice';
// 读取
if (isset($_SESSION['user_id'])) {
echo "欢迎回来,{$_SESSION['username']}";
}
// Cookie(7 天后过期)
setcookie('theme', 'dark', time() + 7 * 86400, '/');
echo $_COOKIE['theme'] ?? 'light';
// 异常
try {
$pdo = new PDO('mysql:host=localhost;dbname=nonexistent', 'root', '');
} catch (PDOException $e) {
error_log($e->getMessage());
http_response_code(500);
echo "数据库连接失败,请稍后重试";
}
// 生产环境配置
ini_set('display_errors', '0');
ini_set('log_errors', '1');
ini_set('error_log', '/var/log/php_errors.log');
CREATE TABLE messages (
id INT AUTO_INCREMENT PRIMARY KEY,
author VARCHAR(100) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
<!-- index.php -->
<form method="POST" action="post.php">
<input name="author" placeholder="你的名字" required>
<textarea name="content" placeholder="想说点什么..." required></textarea>
<button type="submit">发布</button>
</form>
<!-- post.php -->
<?php
$pdo = new PDO('mysql:host=localhost;dbname=app;charset=utf8mb4', 'root', '');
$stmt = $pdo->prepare('INSERT INTO messages (author, content) VALUES (:author, :content)');
$stmt->execute([
'author' => htmlspecialchars($_POST['author']),
'content' => htmlspecialchars($_POST['content']),
]);
header('Location: /');
<!-- index.php 继续 -->
<?php
$stmt = $pdo->query('SELECT * FROM messages ORDER BY created_at DESC LIMIT 20');
while ($msg = $stmt->fetch()): ?>
<div class="message">
<strong><?= htmlspecialchars($msg['author']) ?></strong>
<small><?= $msg['created_at'] ?></small>
<p><?= nl2br(htmlspecialchars($msg['content'])) ?></p>
</div>
<?php endwhile; ?>
htmlspecialchars()? 如果去掉会有什么安全隐患?PDO::prepare 为什么必要? 写一个易受 SQL 注入攻击的代码,再用预处理修复。掌握以上内容,你就具备了用 PHP 从零构建动态网站的核心能力。