本文目录导读:

- 什么是 PHP Boilerplate
- 基本项目结构
- 基础 Boilerplate 示例
- 配置文件 (config.php)
- .htaccess 配置
- 模型基类 (Model.php)
- 使用 Composer 的 Boilerplate
- 模板引擎集成 (可选)
- 安全加固
- 快速开始脚本
- 最佳实践
我来详细介绍 PHP Boilerplate(样板代码/脚手架)的创建和使用方法。
什么是 PHP Boilerplate
Boilerplate 是预先写好的代码模板,可以帮助你快速启动新项目,避免重复编写基础代码。
基本项目结构
project/
├── public/ # 公开访问目录
│ ├── index.php # 入口文件
│ ├── css/ # 样式文件
│ └── js/ # JavaScript文件
├── src/ # 源代码
│ ├── Core/ # 核心类
│ ├── Models/ # 数据模型
│ ├── Views/ # 视图文件
│ └── Controllers/ # 控制器
├── config/ # 配置文件
├── vendor/ # 依赖包
└── .htaccess # Apache配置
基础 Boilerplate 示例
1 入口文件 (index.php)
<?php
declare(strict_types=1);
/**
* PHP Boilerplate 入口文件
*/
// 1. 定义常量
define('ROOT_PATH', __DIR__ . '/../');
define('APP_PATH', ROOT_PATH . 'src/');
define('VIEW_PATH', APP_PATH . 'Views/');
// 2. 加载配置
require_once ROOT_PATH . 'config/config.php';
// 3. 自动加载类
spl_autoload_register(function ($className) {
$prefix = 'App\\';
$baseDir = APP_PATH;
// 检查类名前缀
$len = strlen($prefix);
if (strncmp($prefix, $className, $len) !== 0) {
return;
}
// 获取相对类名并转换路径
$relativeClass = substr($className, $len);
$file = $baseDir . str_replace('\\', '/', $relativeClass) . '.php';
// 加载文件
if (file_exists($file)) {
require $file;
}
});
// 4. 错误处理
error_reporting(E_ALL);
ini_set('display_errors', '1');
// 5. 启动应用
use App\Core\Router;
use App\Core\Request;
use App\Core\Response;
$router = new Router();
$request = new Request();
$response = new Response();
// 定义路由
$router->get('/', 'HomeController@index');
$router->get('/users', 'UserController@index');
$router->post('/users', 'UserController@create');
// 运行应用
try {
$router->dispatch($request, $response);
} catch (Exception $e) {
$response->setStatusCode(500);
echo "Error: " . $e->getMessage();
}
2 路由类 (Router.php)
<?php
namespace App\Core;
/**
* 简单路由器
*/
class Router
{
private array $routes = [
'GET' => [],
'POST' => [],
'PUT' => [],
'DELETE' => []
];
public function get(string $path, string $handler): void
{
$this->addRoute('GET', $path, $handler);
}
public function post(string $path, string $handler): void
{
$this->addRoute('POST', $path, $handler);
}
public function put(string $path, string $handler): void
{
$this->addRoute('PUT', $path, $handler);
}
public function delete(string $path, string $handler): void
{
$this->addRoute('DELETE', $path, $handler);
}
private function addRoute(string $method, string $path, string $handler): void
{
$this->routes[$method][$path] = $handler;
}
public function dispatch(Request $request, Response $response): void
{
$method = $request->getMethod();
$uri = $request->getUri();
// 查找路由
if (isset($this->routes[$method][$uri])) {
$handler = $this->routes[$method][$uri];
[$controller, $action] = explode('@', $handler);
$controllerClass = 'App\\Controllers\\' . $controller;
if (class_exists($controllerClass)) {
$controllerObj = new $controllerClass();
if (method_exists($controllerObj, $action)) {
$controllerObj->{$action}($request, $response);
return;
}
}
}
// 404处理
$response->setStatusCode(404);
$response->setContent('Page not found');
$response->send();
}
}
3 请求和响应类
<?php
namespace App\Core;
/**
* 请求处理类
*/
class Request
{
public function getMethod(): string
{
return $_SERVER['REQUEST_METHOD'];
}
public function getUri(): string
{
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
return rtrim($uri, '/') ?: '/';
}
public function getPost(string $key = null)
{
if ($key === null) {
return $_POST;
}
return $_POST[$key] ?? null;
}
public function getQuery(string $key = null)
{
if ($key === null) {
return $_GET;
}
return $_GET[$key] ?? null;
}
public function getJson()
{
return json_decode(file_get_contents('php://input'), true) ?? [];
}
}
/**
* 响应处理类
*/
class Response
{
private int $statusCode = 200;
private string $content = '';
private array $headers = [];
public function setStatusCode(int $code): void
{
$this->statusCode = $code;
}
public function setContent(string $content): void
{
$this->content = $content;
}
public function setHeader(string $name, string $value): void
{
$this->headers[$name] = $value;
}
public function json(mixed $data): void
{
$this->setHeader('Content-Type', 'application/json');
$this->content = json_encode($data);
}
public function send(): void
{
http_response_code($this->statusCode);
foreach ($this->headers as $name => $value) {
header("$name: $value");
}
echo $this->content;
}
}
配置文件 (config.php)
<?php
/**
* 配置文件
*/
return [
'app' => [
'name' => 'My PHP Application',
'env' => 'development', // development, production
'debug' => true,
'url' => 'http://localhost',
],
'database' => [
'host' => 'localhost',
'port' => 3306,
'database' => 'myapp',
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
],
'security' => [
'secret_key' => 'your-secret-key-here',
'token_expire' => 3600, // 1 hour
],
'paths' => [
'logs' => ROOT_PATH . 'logs/',
'uploads' => ROOT_PATH . 'public/uploads/',
]
];
.htaccess 配置
Options -Indexes
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Force HTTPS
# RewriteCond %{HTTPS} !=on
# RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Remove trailing slashes
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Route all requests to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
# Security headers
<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"
Header set X-XSS-Protection "1; mode=block"
</IfModule>
# Disable directory browsing
Options -Indexes
# Block access to sensitive files
<FilesMatch "(\.(htaccess|htpasswd|ini|log|sh|inc|bak)$|config\.json|composer\.json)">
Order allow,deny
Deny from all
</FilesMatch>
模型基类 (Model.php)
<?php
namespace App\Core;
use PDO;
use PDOException;
/**
* 数据库模型基类
*/
abstract class Model
{
protected PDO $connection;
protected string $table;
protected string $primaryKey = 'id';
public function __construct()
{
$this->connect();
}
private function connect(): void
{
$config = require ROOT_PATH . 'config/config.php';
$dbConfig = $config['database'];
try {
$dsn = "mysql:host={$dbConfig['host']};dbname={$dbConfig['database']};charset={$dbConfig['charset']}";
$this->connection = new PDO(
$dsn,
$dbConfig['username'],
$dbConfig['password'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]
);
} catch (PDOException $e) {
throw new PDOException("Database connection failed: " . $e->getMessage());
}
}
public function findAll(): array
{
$stmt = $this->connection->prepare("SELECT * FROM {$this->table}");
$stmt->execute();
return $stmt->fetchAll();
}
public function findById(int $id)
{
$stmt = $this->connection->prepare("SELECT * FROM {$this->table} WHERE {$this->primaryKey} = ?");
$stmt->execute([$id]);
return $stmt->fetch();
}
public function create(array $data): int
{
$columns = implode(', ', array_keys($data));
$placeholders = ':' . implode(', :', array_keys($data));
$sql = "INSERT INTO {$this->table} ({$columns}) VALUES ({$placeholders})";
$stmt = $this->connection->prepare($sql);
foreach ($data as $key => $value) {
$stmt->bindValue(":$key", $value);
}
$stmt->execute();
return (int)$this->connection->lastInsertId();
}
public function update(int $id, array $data): bool
{
$fields = [];
foreach ($data as $key => $value) {
$fields[] = "$key = :$key";
}
$sql = "UPDATE {$this->table} SET " . implode(', ', $fields) . " WHERE {$this->primaryKey} = :id";
$stmt = $this->connection->prepare($sql);
$stmt->bindValue(':id', $id);
foreach ($data as $key => $value) {
$stmt->bindValue(":$key", $value);
}
return $stmt->execute();
}
public function delete(int $id): bool
{
$stmt = $this->connection->prepare("DELETE FROM {$this->table} WHERE {$this->primaryKey} = ?");
return $stmt->execute([$id]);
}
}
使用 Composer 的 Boilerplate
如果你想使用现成的 Boilerplate,推荐以下方案:
1 使用 Laravel
composer create-project --prefer-dist laravel/laravel my-app
2 使用 Symfony Skeleton
composer create-project symfony/skeleton my-app
3 使用 Slim Framework
composer create-project slim/slim-skeleton my-app
模板引擎集成 (可选)
<?php
// 使用 Twig 模板引擎
require_once 'vendor/autoload.php';
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
$loader = new FilesystemLoader(VIEW_PATH);
$twig = new Environment($loader, [
'cache' => ROOT_PATH . 'cache/twig/',
'debug' => true,
]);
// 在你的控制器中使用
$twig->render('home/index.html', ['name' => 'World']);
安全加固
<?php
// SecurityHelper.php
namespace App\Helpers;
class Security
{
public static function sanitize(string $data): string
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
public static function validateEmail(string $email): bool
{
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
public static function generateCsrfToken(): string
{
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
public static function validateCsrfToken(): bool
{
$token = $_POST['csrf_token'] ?? '';
return isset($_SESSION['csrf_token']) &&
hash_equals($_SESSION['csrf_token'], $token);
}
}
快速开始脚本
创建 create_project.php:
<?php
/**
* 快速创建项目结构的脚本
*/
$projectName = readline("Project name: ");
$projectPath = getcwd() . '/' . $projectName;
// 创建目录结构
$dirs = [
'public/css',
'public/js',
'public/uploads',
'src/Core',
'src/Models',
'src/Views',
'src/Controllers',
'src/Helpers',
'config',
'logs',
'cache',
];
foreach ($dirs as $dir) {
if (!file_exists("$projectPath/$dir")) {
mkdir("$projectPath/$dir", 0777, true);
}
}
echo "Project $projectName created successfully!\n";
最佳实践
-
保持简单:不要过度设计,从小开始
-
使用命名空间:组织代码结构
-
遵循 PSR 标准:PSR-4自动加载,PSR-12编码规范
-
分离关注点:MVC模式
-
配置管理:环境配置文件分离
-
错误处理:开发和生产环境不同的错误处理
-
安全考虑:SQL注入、XSS攻击防护
-
性能优化:使用OPcache缓存,合理使用数据库
这个基础 Boilerplate 可以帮助你快速开始新项目,根据实际需求可以选择使用现有的框架(如 Laravel)或在此基础上扩展,记住要从简单开始,逐步添加功能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播