前言
PHP(Hypertext Preprocessor)是 Web 开发领域最成熟的语言之一。全球超过 75% 的网站使用 PHP,包括 WordPress、Facebook(早期)、Wikipedia。PHP 以部署简单、生态成熟、开发速度快著称。
本文将从零开始,带你系统掌握 PHP 的核心基础。
为什么选择 PHP?
| 优势 |
说明 |
| 🚀 即写即用 |
无需编译,保存即生效 |
| 🌐 为 Web 而生 |
天然支持 HTML 混写,处理表单、Cookie、Session 极方便 |
| 📦 生态成熟 |
Composer + Packagist 海量类库 |
| 💰 成本低 |
几乎所有虚拟主机都支持,云服务器部署简单 |
| 🎯 框架丰富 |
Laravel、Symfony、ThinkPHP 等 |
一、环境搭建
1.1 安装 PHP
Windows:下载 XAMPP 或 PHPStudy
Linux:
1
| sudo apt install php php-cli php-fpm php-mysql php-curl php-mbstring
|
macOS:
1.2 验证安装
1.3 运行 PHP 代码
1 2 3 4 5
| php hello.php
php -S localhost:8000
|
二、第一个 PHP 程序
1 2 3 4 5 6 7 8 9 10
| <!DOCTYPE html> <html> <head> <title>第一个 PHP 程序</title> </head> <body> <h1><?php echo "Hello, 七月小站!"; ?></h1> <p>现在时间是: <?php echo date("Y-m-d H:i:s"); ?></p> </body> </html>
|
💡 PHP 文件可以混合 HTML 和 PHP 代码。<?php ... ?> 标签内的代码在服务端执行,生成 HTML 后返回浏览器。
三、变量与数据类型
3.1 变量
PHP 变量以 $ 开头,松类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?php
$name = "July"; $age = 25; $height = 1.75; $isActive = true;
$varName = "age"; echo $$varName;
$a = 10; $b = &$a; $b = 20; echo $a;
echo $name; var_dump($age); print_r($name);
echo "姓名: {$name}, 年龄: {$age}"; echo '姓名: ' . $name; ?>
|
3.2 数据类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| $int = 42; $float = 3.14; $string = "Hello"; $bool = true;
$array = [1, 2, 3]; $object = new stdClass();
$null = null;
echo gettype($int); echo is_int($int) ? "是整数" : "不是整数"; $strNum = (string) $int; $intNum = (int) "123";
|
3.3 字符串操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| $str = "Hello, PHP!";
echo strlen($str); echo strpos($str, "PHP"); echo str_replace("PHP", "World", $str); echo strtoupper($str); echo strtolower($str); echo substr($str, 0, 5); echo trim(" hello "); echo str_contains($str, "PHP"); echo str_starts_with($str, "Hel"); echo str_ends_with($str, "!");
$parts = explode(", ", $str); $joined = implode(" - ", $parts);
|
四、数组(PHP 的核心数据结构)⭐
4.1 索引数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| $fruits = ["苹果", "香蕉", "橘子"]; $fruits = array("苹果", "香蕉", "橘子"); $nums = range(1, 5);
echo $fruits[0];
$fruits[] = "草莓"; array_push($fruits, "葡萄"); array_unshift($fruits, "西瓜"); $last = array_pop($fruits); $first = array_shift($fruits); unset($fruits[1]);
foreach ($fruits as $fruit) { echo $fruit . " "; }
foreach ($fruits as $index => $fruit) { echo "{$index}: {$fruit}\n"; }
|
4.2 关联数组(类似字典/Map)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| $person = [ "name" => "July", "age" => 25, "city" => "深圳", "hobbies" => ["编程", "阅读", "摄影"] ];
echo $person["name"]; echo $person["hobbies"][0];
$person["email"] = "july@example.com"; unset($person["city"]);
if (array_key_exists("age", $person)) { echo "age 已设置"; }
if (isset($person["age"])) { echo "age 已设置"; }
foreach ($person as $key => $value) { echo "{$key}: {$value}\n"; }
|
4.3 常用数组函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| $nums = [3, 1, 4, 1, 5, 9, 2, 6];
echo count($nums); echo array_sum($nums); echo max($nums); echo min($nums);
sort($nums); rsort($nums); asort($person); ksort($person);
$evens = array_filter($nums, function($n) { return $n % 2 == 0; });
$doubled = array_map(function($n) { return $n * 2; }, $nums);
$a = ["a" => 1, "b" => 2]; $b = ["b" => 3, "c" => 4]; $merged = array_merge($a, $b);
$spread = [...$a, ...$b];
$unique = array_unique([1, 2, 2, 3, 3, 3]);
$reversed = array_reverse($nums);
$hasCommon = !empty(array_intersect([1, 2], [2, 3]));
|
五、流程控制
5.1 if / else
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| $score = 85;
if ($score >= 90) { $grade = "A"; } elseif ($score >= 80) { $grade = "B"; } elseif ($score >= 60) { $grade = "C"; } else { $grade = "D"; }
echo "等级: {$grade}";
$status = ($age >= 18) ? "成年" : "未成年";
$name = $_GET["name"] ?? "访客";
$config ??= "default";
|
5.2 match 表达式(PHP 8.0+,替代 switch)
1 2 3 4 5 6 7 8 9 10 11 12
| $day = 3; $dayName = match ($day) { 1 => "星期一", 2 => "星期二", 3 => "星期三", 4 => "星期四", 5 => "星期五", 6, 7 => "周末", default => "无效" }; echo $dayName;
|
5.3 传统 switch
1 2 3 4 5 6 7 8 9 10
| switch ($day) { case 1: echo "星期一"; break; case 2: echo "星期二"; break; default: echo "其他"; }
|
5.4 循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| for ($i = 0; $i < 5; $i++) { echo $i . " "; }
$count = 0; while ($count < 5) { echo $count . " "; $count++; }
do { echo "执行"; } while (false);
$fruits = ["苹果", "香蕉", "橘子"]; foreach ($fruits as $fruit) { echo $fruit . "\n"; }
|
六、函数
6.1 基本函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| function greet($name) { return "你好,{$name}!"; }
function add($a, $b = 10) { return $a + $b; }
function multiply(int $a, int $b): int { return $a * $b; }
function getUser(?int $id): ?array { if ($id === null) return null; return ["id" => $id, "name" => "July"]; }
echo add(b: 5, a: 3);
function sumAll(...$nums) { return array_sum($nums); } echo sumAll(1, 2, 3, 4, 5);
|
6.2 匿名函数(闭包)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| $double = function($x) { return $x * 2; }; echo $double(5);
$multiplier = 3; $triple = function($x) use ($multiplier) { return $x * $multiplier; }; echo $triple(5);
$multiplier = 3; $triple = fn($x) => $x * $multiplier; echo $triple(5);
$nums = [1, 2, 3, 4, 5]; $doubled = array_map(fn($n) => $n * 2, $nums);
|
6.3 变量作用域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| $globalVar = "全局变量";
function test() { $localVar = "局部变量"; global $globalVar; echo $globalVar; echo $GLOBALS["globalVar"]; }
function counter() { static $count = 0; $count++; return $count; } echo counter(); echo counter(); echo counter();
|
七、面向对象编程(OOP)
7.1 类与对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| class User { public string $username; public string $email; private string $password; protected int $age; public static int $count = 0; const ROLE_USER = "user"; const ROLE_ADMIN = "admin"; public function __construct( string $username, string $email, string $password, int $age = 18 ) { $this->username = $username; $this->email = $email; $this->password = password_hash($password, PASSWORD_DEFAULT); $this->age = $age; self::$count++; } public function getAge(): int { return $this->age; } public function setAge(int $age): void { if ($age < 0 || $age > 150) { throw new InvalidArgumentException("无效的年龄"); } $this->age = $age; } public function greet(): string { return "你好,我是{$this->username}"; } public function verifyPassword(string $password): bool { return password_verify($password, $this->password); } public static function getCount(): int { return self::$count; } public function __destruct() { } public function __toString(): string { return "User({$this->username})"; } }
$user1 = new User("July", "july@example.com", "secret123", 25); $user2 = new User("zhangsan", "zhangsan@example.com", "pass456");
echo $user1->greet(); echo User::$count; echo User::ROLE_ADMIN; echo $user1;
|
7.2 继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| class Animal { public function __construct( protected string $name ) {} public function speak(): string { return "..."; } public function getName(): string { return $this->name; } }
class Dog extends Animal { public function __construct( string $name, private string $breed ) { parent::__construct($name); } public function speak(): string { return "汪汪汪!"; } public function getBreed(): string { return $this->breed; } }
class Cat extends Animal { public function speak(): string { return "喵喵喵!"; } }
$animals = [ new Dog("旺财", "金毛"), new Cat("小花"), ];
foreach ($animals as $animal) { echo "{$animal->getName()} 说: {$animal->speak()}\n"; }
|
7.3 接口与抽象类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| interface LoggerInterface { public function log(string $message): void; }
interface FormatterInterface { public function format(string $message): string; }
class FileLogger implements LoggerInterface, FormatterInterface { public function __construct(private string $filepath) {} public function log(string $message): void { $formatted = $this->format($message); file_put_contents($this->filepath, $formatted . "\n", FILE_APPEND); } public function format(string $message): string { return sprintf("[%s] %s", date("Y-m-d H:i:s"), $message); } }
function runApp(LoggerInterface $logger): void { $logger->log("应用启动"); }
trait Timestampable { private \DateTime $createdAt; private \DateTime $updatedAt; public function initTimestamps(): void { $this->createdAt = new \DateTime(); $this->updatedAt = new \DateTime(); } public function getCreatedAt(): \DateTime { return $this->createdAt; } }
class Article { use Timestampable; public function __construct(string $title) { $this->initTimestamps(); } }
|
八、表单处理
PHP 处理表单是最常见的 Web 开发场景。
8.1 HTML 表单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <form action="submit.php" method="POST" enctype="multipart/form-data"> <label>姓名:<input type="text" name="username" required></label><br> <label>邮箱:<input type="email" name="email"></label><br> <label>年龄:<input type="number" name="age" min="1" max="150"></label><br> <label>性别: <input type="radio" name="gender" value="male"> 男 <input type="radio" name="gender" value="female"> 女 </label><br> <label>爱好: <input type="checkbox" name="hobbies[]" value="coding"> 编程 <input type="checkbox" name="hobbies[]" value="reading"> 阅读 <input type="checkbox" name="hobbies[]" value="sports"> 运动 </label><br> <label>个人简介:<textarea name="bio"></textarea></label><br> <label>头像:<input type="file" name="avatar"></label><br> <button type="submit">提交</button> </form>
|
8.2 处理表单数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| <?php
if ($_SERVER["REQUEST_METHOD"] !== "POST") { die("只接受 POST 请求"); }
$username = trim($_POST["username"] ?? ""); $email = filter_input(INPUT_POST, "email", FILTER_VALIDATE_EMAIL); $age = (int) ($_POST["age"] ?? 0); $gender = $_POST["gender"] ?? "未指定"; $hobbies = $_POST["hobbies"] ?? []; $bio = strip_tags($_POST["bio"] ?? "");
$errors = [];
if (empty($username)) { $errors[] = "姓名不能为空"; } if (!$email) { $errors[] = "邮箱格式不正确"; } if ($age < 1 || $age > 150) { $errors[] = "年龄不合理"; }
if (isset($_FILES["avatar"]) && $_FILES["avatar"]["error"] === UPLOAD_ERR_OK) { $allowedTypes = ["image/jpeg", "image/png", "image/gif"]; $maxSize = 2 * 1024 * 1024; $file = $_FILES["avatar"]; if (!in_array($file["type"], $allowedTypes)) { $errors[] = "只允许 JPG/PNG/GIF 格式"; } if ($file["size"] > $maxSize) { $errors[] = "文件不能超过 2MB"; } if (empty($errors)) { $ext = pathinfo($file["name"], PATHINFO_EXTENSION); $newName = uniqid("avatar_") . "." . $ext; $uploadPath = __DIR__ . "/uploads/" . $newName; if (!is_dir(__DIR__ . "/uploads")) { mkdir(__DIR__ . "/uploads", 0755, true); } move_uploaded_file($file["tmp_name"], $uploadPath); echo "头像上传成功: {$newName}<br>"; } }
if (!empty($errors)) { foreach ($errors as $error) { echo "<p style='color:red'>❌ {$error}</p>"; } exit; }
echo "<h2>提交成功!</h2>"; echo "<p>姓名: " . htmlspecialchars($username) . "</p>"; echo "<p>邮箱: " . htmlspecialchars($email) . "</p>"; echo "<p>年龄: {$age}</p>"; echo "<p>性别: {$gender}</p>"; echo "<p>爱好: " . implode(", ", $hobbies) . "</p>"; ?>
|
九、数据库操作(MySQL + PDO)
PDO(PHP Data Objects)是 PHP 访问数据库的统一接口,安全、支持预处理语句。
9.1 数据库连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <?php
function getDB(): PDO { static $pdo = null; if ($pdo === null) { $host = "localhost"; $dbname = "my_blog"; $username = "root"; $password = "your_password"; $charset = "utf8mb4"; $dsn = "mysql:host={$host};dbname={$dbname};charset={$charset}"; $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; $pdo = new PDO($dsn, $username, $password, $options); } return $pdo; } ?>
|
9.2 CRUD 操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| <?php require_once "database.php";
$db = getDB();
$stmt = $db->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)"); $stmt->execute(["July", "july@example.com", password_hash("secret123", PASSWORD_DEFAULT)]); $newId = $db->lastInsertId(); echo "新增用户 ID: {$newId}<br>";
$stmt = $db->prepare("INSERT INTO users (username, email, password) VALUES (:name, :email, :pass)"); $stmt->execute([ ":name" => "zhangsan", ":email" => "zhangsan@example.com", ":pass" => password_hash("pass456", PASSWORD_DEFAULT), ]);
$stmt = $db->query("SELECT id, username, email, created_at FROM users ORDER BY id DESC"); $users = $stmt->fetchAll(); foreach ($users as $user) { echo "{$user["id"]}: {$user["username"]} ({$user["email"]})<br>"; }
$stmt = $db->prepare("SELECT * FROM users WHERE username = ?"); $stmt->execute(["July"]); $user = $stmt->fetch(); if ($user) { echo "找到用户: {$user["username"]}<br>"; }
$page = (int) ($_GET["page"] ?? 1); $perPage = 10; $offset = ($page - 1) * $perPage;
$stmt = $db->prepare("SELECT * FROM users ORDER BY id DESC LIMIT ? OFFSET ?"); $stmt->execute([$perPage, $offset]); $users = $stmt->fetchAll();
$total = $db->query("SELECT COUNT(*) FROM users")->fetchColumn(); $totalPages = ceil($total / $perPage);
$stmt = $db->prepare("UPDATE users SET email = ?, updated_at = NOW() WHERE id = ?"); $stmt->execute(["new_email@example.com", $newId]); echo "更新了 {$stmt->rowCount()} 行<br>";
$stmt = $db->prepare("DELETE FROM users WHERE id = ?"); $stmt->execute([$newId]); echo "删除了 {$stmt->rowCount()} 行<br>"; ?>
|
9.3 安全查询要点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| $username = $_GET["username"]; $db->query("SELECT * FROM users WHERE username = '{$username}'");
$stmt = $db->prepare("SELECT * FROM users WHERE username = ?"); $stmt->execute([$_GET["username"]]);
$ids = [1, 2, 3, 4, 5]; $placeholders = implode(",", array_fill(0, count($ids), "?")); $stmt = $db->prepare("SELECT * FROM users WHERE id IN ({$placeholders})"); $stmt->execute($ids);
$keyword = $_GET["q"] ?? ""; $stmt = $db->prepare("SELECT * FROM posts WHERE title LIKE ?"); $stmt->execute(["%{$keyword}%"]);
|
9.4 简单的事务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| try { $db->beginTransaction(); $stmt = $db->prepare("INSERT INTO posts (title, content, user_id) VALUES (?, ?, ?)"); $stmt->execute(["文章标题", "文章内容", 1]); $postId = $db->lastInsertId(); $stmt = $db->prepare("INSERT INTO post_tags (post_id, tag_id) VALUES (?, ?)"); $stmt->execute([$postId, 5]); $stmt->execute([$postId, 8]); $db->commit(); echo "文章发布成功!"; } catch (Exception $e) { $db->rollBack(); echo "发布失败: " . $e->getMessage(); }
|
十、Cookie 与 Session
10.1 Cookie(客户端存储)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| setcookie("username", "July", time() + 3600 * 24 * 30, "/"); setcookie("theme", "dark", [ "expires" => time() + 3600 * 24 * 30, "path" => "/", "secure" => true, // 仅 HTTPS "httponly" => true, // JS 无法访问 "samesite" => "Lax", ]);
$username = $_COOKIE["username"] ?? null;
setcookie("username", "", time() - 3600, "/");
|
10.2 Session(服务端存储)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| session_start();
$_SESSION["user_id"] = 42; $_SESSION["username"] = "July"; $_SESSION["logged_in"] = true; $_SESSION["cart"] = [ ["id" => 1, "name" => "商品A", "qty" => 2], ["id" => 2, "name" => "商品B", "qty" => 1], ];
$userName = $_SESSION["username"] ?? "访客";
unset($_SESSION["cart"]);
session_destroy();
session_start(); function isLoggedIn(): bool { return isset($_SESSION["user_id"]); }
function requireLogin(): void { if (!isLoggedIn()) { header("Location: /login.php"); exit; } }
|
十一、文件操作与常用函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| $content = file_get_contents("data.txt"); $lines = file("data.txt");
file_put_contents("output.txt", "Hello World\n"); file_put_contents("output.txt", "追加内容\n", FILE_APPEND);
if (file_exists("data.txt")) { echo "文件大小: " . filesize("data.txt") . " 字节"; echo "修改时间: " . date("Y-m-d", filemtime("data.txt")); }
$files = scandir("/path/to/dir"); is_dir("/path"); mkdir("/path/to/newdir", 0755, true);
htmlspecialchars("<script>alert('xss')</script>"); strip_tags("<p>Hello</p><script>evil()</script>"); urlencode("搜索 关键词"); json_encode(["name" => "July"], JSON_UNESCAPED_UNICODE); json_decode('{"name":"July"}', true);
echo date("Y-m-d H:i:s"); echo date("Y-m-d H:i:s", strtotime("+1 week")); echo time();
|
十二、实战:简易博客 API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| <?php
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");
if ($_SERVER["REQUEST_METHOD"] === "OPTIONS") { http_response_code(200); exit; }
require_once "database.php"; $db = getDB();
$method = $_SERVER["REQUEST_METHOD"]; $path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
if (preg_match('#^/api/articles$#', $path)) { switch ($method) { case "GET": $stmt = $db->query("SELECT * FROM posts WHERE status = 1 ORDER BY id DESC LIMIT 20"); $articles = $stmt->fetchAll(); echo json_encode(["code" => 200, "data" => $articles], JSON_UNESCAPED_UNICODE); break; case "POST": $input = json_decode(file_get_contents("php://input"), true); if (empty($input["title"]) || empty($input["content"])) { http_response_code(400); echo json_encode(["code" => 400, "msg" => "标题和内容不能为空"]); exit; } $stmt = $db->prepare("INSERT INTO posts (title, content, user_id) VALUES (?, ?, ?)"); $stmt->execute([$input["title"], $input["content"], $input["user_id"] ?? 1]); echo json_encode([ "code" => 201, "msg" => "创建成功", "id" => $db->lastInsertId() ], JSON_UNESCAPED_UNICODE); break; default: http_response_code(405); echo json_encode(["code" => 405, "msg" => "方法不允许"]); } } elseif (preg_match('#^/api/articles/(\d+)$#', $path, $matches)) { $id = (int) $matches[1]; switch ($method) { case "GET": $stmt = $db->prepare("SELECT * FROM posts WHERE id = ?"); $stmt->execute([$id]); $article = $stmt->fetch(); if (!$article) { http_response_code(404); echo json_encode(["code" => 404, "msg" => "文章不存在"]); exit; } echo json_encode(["code" => 200, "data" => $article], JSON_UNESCAPED_UNICODE); break; case "PUT": $input = json_decode(file_get_contents("php://input"), true); $stmt = $db->prepare("UPDATE posts SET title = ?, content = ?, updated_at = NOW() WHERE id = ?"); $stmt->execute([$input["title"], $input["content"], $id]); echo json_encode(["code" => 200, "msg" => "更新成功"]); break; case "DELETE": $stmt = $db->prepare("DELETE FROM posts WHERE id = ?"); $stmt->execute([$id]); echo json_encode(["code" => 200, "msg" => "删除成功"]); break; default: http_response_code(405); echo json_encode(["code" => 405, "msg" => "方法不允许"]); } } else { http_response_code(404); echo json_encode(["code" => 404, "msg" => "路由不存在"]); } ?>
|
启动并测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| php -S localhost:8000
curl http://localhost:8000/api/articles
curl -X POST http://localhost:8000/api/articles \ -H "Content-Type: application/json" \ -d '{"title":"PHP基础教程","content":"这是内容","user_id":1}'
curl http://localhost:8000/api/articles/1
curl -X PUT http://localhost:8000/api/articles/1 \ -H "Content-Type: application/json" \ -d '{"title":"PHP进阶教程","content":"更新的内容"}'
curl -X DELETE http://localhost:8000/api/articles/1
|
十三、Composer 与第三方库
1 2 3 4 5 6 7 8 9 10
|
curl -sS https://getcomposer.org/installer | php sudo mv composer.phar /usr/local/bin/composer
composer init composer require phpmailer/phpmailer composer require monolog/monolog composer install
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <?php require_once "vendor/autoload.php";
use Monolog\Logger; use Monolog\Handler\StreamHandler;
$log = new Logger("myapp"); $log->pushHandler(new StreamHandler("app.log", Logger::WARNING)); $log->warning("这是一个警告"); $log->error("发生错误", ["user_id" => 42]);
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true); $mail->setFrom("from@example.com", "七月小站"); $mail->addAddress("to@example.com"); $mail->Subject = "测试邮件"; $mail->Body = "<h1>Hello</h1><p>这是一封测试邮件</p>"; $mail->isHTML(true); $mail->send(); ?>
|
常用 PHP 命令速查
| 命令 |
说明 |
php -v |
查看 PHP 版本 |
php file.php |
运行 PHP 文件 |
php -S localhost:8000 |
启动开发服务器 |
php -m |
列出已安装的扩展模块 |
php -i |
显示 PHP 配置信息(phpinfo) |
php -r "echo 'hello';" |
执行一行 PHP 代码 |
composer install |
安装依赖 |
composer require pkg |
添加新的依赖包 |
安全最佳实践
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| echo htmlspecialchars($userInput, ENT_QUOTES, "UTF-8");
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$id]);
session_start(); if ($_SERVER["REQUEST_METHOD"] === "POST") { if ($_POST["csrf_token"] !== $_SESSION["csrf_token"]) { die("CSRF 验证失败"); } } $_SESSION["csrf_token"] = bin2hex(random_bytes(32));
$hashed = password_hash($password, PASSWORD_DEFAULT);
password_verify($inputPassword, $hashed);
$allowed = ["image/jpeg", "image/png"]; $finfo = finfo_open(FILEINFO_MIME_TYPE); $mime = finfo_file($finfo, $_FILES["file"]["tmp_name"]); if (!in_array($mime, $allowed)) { die("不允许的文件类型"); }
|
进一步学习
- Web 框架:Laravel(全栈)、Symfony(企业级)、ThinkPHP(国产)
- CMS:WordPress 主题/插件开发
- 模板引擎:Blade(Laravel)、Twig(Symfony)
- 测试:PHPUnit
- 设计模式:工厂模式、单例模式、依赖注入等在 PHP 中的实践
结语
PHP 作为互联网的”老黄牛”,支撑着全球 75% 以上的网站。它上手简单、部署方便、生态丰富,非常适合快速开发 Web 应用。
本文涵盖了 PHP 开发中最核心的知识点。配合现代 PHP 8.x 的新特性(命名参数、match 表达式、类型系统、JIT 编译器等),PHP 的开发体验已经今非昔比。
别听别人说”PHP 是最好的语言”或”PHP 已死”——自己去写个小项目感受一下吧!🐘