PHP网站设计怎么入门?目录结构、路由、数据库设计与基础安全
PHP网站设计怎么入门?目录结构、路由、数据库设计与基础安全
PHP 网站设计入门,关键不在于背语法,而在于先把网站的"骨架"想清楚:一个入口文件接收所有请求,路由把请求分发给对应的处理代码,处理代码通过数据库层读写数据,再交给模板输出页面。把这条线理顺,哪怕不用任何框架,也能写出结构清晰、方便维护的小型站点。
本文以"一个带文章列表和详情页的小型内容站"为例,按目录结构、入口与路由、数据库设计、模板分离、基础安全的顺序,讲解基于 PHP 的网站设计思路,并给出简短的代码示例。示例面向 PHP 7.4 及以上版本,选型与框架对比、漏洞排查不在本文展开,可以参考站内技术栏目的相关文章。
一、先理解 PHP 站点的基本流程
一次访问网页,在 PHP 站点里大致经历这几步:
- 浏览器发出请求,Web 服务器(Nginx 或 Apache)把请求交给 PHP 处理。
- PHP 执行入口文件,读取配置、启动会话、加载需要的代码。
- 根据网址判断要执行哪段业务逻辑(路由)。
- 业务逻辑查询或写入数据库,得到数据。
- 把数据交给模板,生成 HTML。
- 把 HTML 返回给浏览器。
初学者常见的问题,是把第 2 到第 5 步全部写在同一个文件里:一边查数据库,一边拼 HTML,还夹杂着判断逻辑。小站点刚开始能跑,页面一多就难以维护。设计的目的,就是把这几步拆开。
二、目录结构怎么分
下面是一个适合小型站点的目录结构:
mysite/
├── public/ # 对外开放的目录(Web 根目录)
│ ├── index.php # 入口文件
│ ├── css/
│ ├── js/
│ └── uploads/ # 上传文件(需限制可执行)
├── app/
│ ├── config.php # 配置(数据库、站点名等)
│ ├── db.php # 数据库连接
│ ├── routes.php # 路由表
│ ├── controllers/ # 业务处理
│ │ ├── HomeController.php
│ │ └── ArticleController.php
│ ├── models/ # 数据读写
│ │ └── Article.php
│ └── views/ # 模板
│ ├── layout.php
│ ├── home.php
│ └── article_show.php
└── storage/ # 日志、缓存(不对外)
这个结构有几条重要的设计原则:
- 只把
public/作为 Web 根目录:配置文件、业务代码、日志都放在根目录之外,即使服务器配置出问题,也不会被直接访问到。 - 按职责分层:控制器负责处理请求,模型负责读写数据,视图负责输出页面,互相之间依赖关系清晰。
- 配置集中管理:数据库账号、站点名称等放在配置文件中,不散落在各处。
- 上传目录单独隔离:上传目录里不允许执行脚本,这点在服务器配置里要单独设置。
三、入口文件与简单路由
所有请求都由 public/index.php 接收,再由它分发。先看一个最简版本的入口文件:
<?php
// public/index.php
declare(strict_types=1);
require __DIR__ . '/../app/config.php';
require __DIR__ . '/../app/db.php';
$routes = require __DIR__ . '/../app/routes.php';
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
foreach ($routes as [$routeMethod, $pattern, $handler]) {
if ($routeMethod === $method && preg_match($pattern, $path, $matches)) {
array_shift($matches);
[$class, $action] = $handler;
require __DIR__ . '/../app/controllers/' . $class . '.php';
(new $class())->$action(...$matches);
exit;
}
}
http_response_code(404);
echo '页面不存在';
路由表可以非常简单:
<?php
// app/routes.php
return [
['GET', '#^/$#', ['HomeController', 'index']],
['GET', '#^/article/(\d+)$#', ['ArticleController', 'show']],
];
要让 /article/12 这样的网址生效,需要 Web 服务器把不存在的文件请求都转发给 index.php。以 Nginx 为例,核心配置是:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
这样做的好处:网址整洁,对搜索引擎友好;所有请求经过同一个入口,方便统一做日志、权限、错误处理。
四、数据库怎么设计
入门阶段不要追求复杂,关键是把表结构设计得"够用、不浪费"。以文章表为例:
CREATE TABLE article (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
title VARCHAR(200) NOT NULL,
summary VARCHAR(500) NOT NULL DEFAULT '',
content MEDIUMTEXT NOT NULL,
category_id INT UNSIGNED NOT NULL DEFAULT 0,
status TINYINT NOT NULL DEFAULT 1,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
PRIMARY KEY (id),
KEY idx_category (category_id),
KEY idx_status_created (status, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
设计时可以遵循这些习惯:
- 每张表都有自增主键:简单、稳定,便于关联和分页。
- 字符集用 utf8mb4:能存储中文和 emoji,避免乱码。
- 给常用查询条件建索引:比如按分类查、按状态加时间排序,索引要贴合实际查询。
- 字段类型贴合内容:标题用
VARCHAR,正文用TEXT系列,状态用TINYINT。 - 预留时间字段:创建时间和更新时间几乎总会用到。
- 不要把多个含义塞进同一个字段:比如用逗号拼接多个标签,后期查询会很麻烦,应该拆成关联表。
数据库连接推荐使用 PDO,并开启异常模式:
<?php
// app/db.php
function db(): PDO {
static $pdo = null;
if ($pdo === null) {
$cfg = require __DIR__ . '/config.php';
$dsn = "mysql:host={$cfg['db_host']};dbname={$cfg['db_name']};charset=utf8mb4";
$pdo = new PDO($dsn, $cfg['db_user'], $cfg['db_pass'], [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
}
return $pdo;
}
五、模型层:把数据读写集中起来
模型层只做一件事:和数据库打交道。控制器不应该直接写 SQL,这样以后换表结构或优化查询时,只需要改模型。
<?php
// app/models/Article.php
class Article {
public static function find(int $id): ?array {
$stmt = db()->prepare('SELECT * FROM article WHERE id = :id AND status = 1');
$stmt->execute([':id' => $id]);
$row = $stmt->fetch();
return $row ?: null;
}
public static function latest(int $limit = 10): array {
$stmt = db()->prepare(
'SELECT id, title, summary, created_at FROM article
WHERE status = 1 ORDER BY created_at DESC LIMIT :n'
);
$stmt->bindValue(':n', $limit, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll();
}
}
这里用到了预处理语句:SQL 里只放占位符,用户传入的值通过参数绑定,这是防止 SQL 注入基础且有效的做法。
六、控制器与模板:逻辑和页面分开
控制器接收请求,调用模型取数据,再把数据交给模板:
<?php
// app/controllers/ArticleController.php
require __DIR__ . '/../models/Article.php';
class ArticleController {
public function show(string $id): void {
$article = Article::find((int)$id);
if (!$article) {
http_response_code(404);
echo '文章不存在';
return;
}
$title = $article['title'];
ob_start();
require __DIR__ . '/../views/article_show.php';
$content = ob_get_clean();
require __DIR__ . '/../views/layout.php';
}
}
模板只负责输出,里面不要出现查询数据库的代码,并且所有来自数据库或用户的内容都要转义后再输出:
<!-- app/views/article_show.php -->
<article>
<h1><?= htmlspecialchars($article['title'], ENT_QUOTES, 'UTF-8') ?></h1>
<div class="meta"><?= htmlspecialchars($article['created_at']) ?></div>
<div class="body"><?= nl2br(htmlspecialchars($article['content'], ENT_QUOTES, 'UTF-8')) ?></div>
</article>
layout.php 放页面公共部分,比如页头、导航、页脚,通过 $title 和 $content 两个变量拼出完整页面。这样每个页面只需要写自己的内容,公共部分改一处全站生效。
七、基础安全:入门阶段必须做到的几件事
安全是一个独立的大话题,这里只列入门时必须养成的习惯,具体的漏洞原理和排查方法,可以参考站内关于 PHP 网站安全的专门文章:
- 所有数据库查询使用预处理语句,不要拼接 SQL 字符串。
- 输出到页面的内容一律转义,防止脚本注入。
- 密码使用
password_hash()存储,password_verify()校验,不要自己写加密逻辑,更不要明文存储。 - 表单提交加 CSRF 令牌,防止被第三方页面诱导提交。
- 上传文件限制类型与大小,并重命名保存,上传目录禁止执行脚本。
- 关闭生产环境的错误回显,错误写进日志,不要把报错信息展示给访客。
- 配置文件放在 Web 根目录之外,数据库账号使用最小权限。
- 保持 PHP 与组件的版本更新,及时修复已知漏洞。
八、从"能跑"到"好维护"的几个进阶方向
当站点跑起来、功能逐渐增多,可以考虑逐步引入:
- 统一的错误处理与日志:用统一的异常处理,把错误记录到文件,便于排查。
- 配置区分环境:开发、测试、生产使用不同的配置,避免误操作。
- 分页与缓存:列表页加分页,热点数据加缓存,减轻数据库压力。
- 后台管理:为内容更新做一个带登录和权限的管理界面。
- 自动化部署与备份:代码用版本管理,数据库定期备份。
- 选用成熟框架:当项目规模变大、团队协作增多,再评估是否引入框架来统一规范。
不必一开始就做这些。先把"入口—路由—控制器—模型—视图"这条线跑通,理解每一层存在的理由,再按需要升级,比一上来就套用复杂框架更容易学扎实。
九、小型站点和正式业务站点的差别
用上面的方式,已经可以做出个人博客、产品展示页、内部小工具这类站点。如果是企业对外的正式官网,需要额外考虑的事情会更多,包括:搜索引擎优化的页面细节、移动端适配、访问速度、后台内容管理、备案、服务器安全与日常维护等。这时是自己继续开发,还是交给专业团队,取决于时间、人力和长期维护的成本。
广州万户网络提供网站建设与软件开发服务,建站套餐的参考价格为 1280 / 2680 / 3880 / 6800 元起,具体档位根据页面数量、设计方式和功能需求评估,以实际需求报价为准,详细内容可查看 建站价格方案。
常见问题
Q:学 PHP 网站设计,要不要一开始就用框架? A:建议先用原生 PHP 把请求流程、路由、数据库和模板的关系理解清楚,再学习框架。这样用框架时,能明白它每一层在做什么,而不是只会照着文档写。
Q:PHP 网站设计里,目录结构为什么要把 public 单独拿出来?
A:只把 public 作为 Web 根目录,配置文件和业务代码放在目录之外,可以避免配置、源码被直接访问,是降低泄露风险的基础做法。
Q:数据库操作用 mysqli 还是 PDO? A:两者都可以,PDO 支持多种数据库,预处理语句写法统一,入门时更方便。关键是无论哪种,都要使用预处理语句和参数绑定。
Q:基于 PHP 的网站设计,数据库表要不要一开始就设计得很完整? A:不需要追求一步到位。先满足当前功能,保证主键、字符集、常用索引合理,后续再根据需求增加字段或拆分表,并做好迁移记录。
Q:做完的 PHP 站点怎么上线? A:需要准备服务器环境(Web 服务器、PHP、数据库)、域名、备案(国内服务器)、HTTPS 证书,并配置好目录权限和伪静态规则,上线前关闭错误回显并做好备份。
如果你想把自己的业务做成一个稳定可维护的网站,却不确定该自己写还是找人做,可以把业务需求和预算告诉我们,广州万户网络可以先帮你评估方案,咨询电话:13535321113。需要更多开发方面的技术内容,也可以浏览 软件开发栏目,把基础打牢之后,再决定下一步怎么走。
需要网站建设、软件开发或爬虫定制?
模板建站1280元起,价格公开不加价。电话/微信 13535321113
