一、为啥要学编码规范?—— 先救救你的头发和同事关系
如果你写过这样的代码:
function doIt($a,$b){if($a>$b){return $a+$b;}else{return $a-$b;}}
恭喜你,你已经成为“团队最想暗杀程序员排行榜”的种子选手!
不规范代码的三大罪状:
- 读代码像破译甲骨文
变量名$a、$tmp1、$data2……请问这是要给变量举办“最无聊命名大赛”吗?一个月后你自己都看不懂,何况接手的新人(可能正在磨刀)。 - 调试时间比写代码长10倍
缩进乱如麻花,if和else隔了五行屏幕远,找bug时眼神得像玩“大家来找茬”。深夜加班改bug?活该,谁让你写代码像草书! - 团队协作变成“代码打架”
你写snake_case函数名,他用camelCase,另一个用匈牙利命名法……合并代码时Git冲突多到像修罗场,最后只能靠吼解决:“你这写的啥玩意儿?!”
说白了,编码规范就是程序员世界的交通规则——没红绿灯的路口,车撞人飞;没规范的代码,人秃心碎。
二、PHP编码规范核心六条“保命法则”
法则1:命名要像给宠物起名,别瞎应付!
- 变量/函数名:用蛇形命名(snake_case)还是驼峰(camelCase)?
PHP官方推荐:变量、函数、方法用 snake_case,类名用 大驼峰(StudlyCase)。
// 坏例子:混搭风,逼死强迫症
$UserName = "张三";
function GetData() {}
class user_model {}
// 好例子:统一才是王道
$user_name = "张三";
function get_data() {}
class UserModel {}
- 起名要有“人话感”,别当谜语人
// 坏例子:这货是干啥的?
$tmp = query($sql); // tmp是临时文件?临时变量?临时工?
function proc() {} // 处理?进程?切土豆?
// 好例子:看名字就懂
$user_list = fetch_users_from_database();
function calculate_order_total() {}
法则2:缩进和大括号——代码的“发型”不能乱
PHP推荐用 4个空格缩进(不许用Tab!因为不同编辑器显示可能不同),大括号换行放还是行尾放?看例子:
// 坏例子:括号乱飞,眼已花
if ($condition){
echo "yes";}
else {echo "no";}
// 好例子:清爽如男团发型
if ($condition) {
echo "yes";
} else {
echo "no";
}
法则3:注释不是日记,少写废话多写“为什么”
// 坏例子:废话注释
$count = 0; // 设置count为0
// 好例子:解释复杂逻辑的意图
// 因为API限制每秒10次请求,需要延迟避免被封
sleep(0.1);
法则4:行长限制——别让代码变成“横屏马拉松”
单行建议不超过80字符,超了就换行:
// 坏例子:需要左右滚动屏幕才能看完
$result = $this->some_really_long_method_name($param1, $param2, $param3, $param4);
// 好例子:拆行更易读
$result = $this->some_really_long_method_name(
$param1,
$param2,
$param3,
$param4
);
法则5:文件结构像衣柜,分门别类别乱塞
- 一个类一个文件,文件名和类名一致(如
UserService.php放UserService类) - 用命名空间(Namespace)做“文件夹划分”:
// 坏例子:所有类扔全局,名字冲突预警!
class Logger {}
class User {}
// 好例子:命名空间隔离
namespace App\Services;
class Logger {}
namespace App\Models;
class User {}
法则6:安全与性能——别让代码成黑客后门
- 永远不要相信用户输入!SQL注入警告:
// 坏例子:黑客狂喜
$sql = "SELECT * FROM users WHERE id = " . $_GET['id'];
// 好例子:参数绑定保平安
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]);
- 及时关数据库连接、用缓存减少重复查询……(细节看后续示例)
三、完整示例:一个规范的用户注册模块
下面是一个符合PSR标准(PHP官方推荐规范)的迷你项目,包含用户注册、验证和日志记录:
项目结构
demo_project/
├── app/
│ ├── Models/
│ │ └── User.php
│ ├── Services/
│ │ ├── UserService.php
│ │ └── LoggerService.php
│ └── Utils/
│ └── Validator.php
├── config/
│ └── database.php
└── public/
└── index.php
代码逐文件解析
1. 数据库配置(config/database.php)
<?php
// 配置用常量定义,大写+下划线
define('DB_HOST', 'localhost');
define('DB_NAME', 'test_db');
define('DB_USER', 'root');
define('DB_PASS', 'password');
// 返回PDO连接,确保错误模式为异常(方便调试)
function get_db_connection()
{
try {
$dsn = sprintf('mysql:host=%s;dbname=%s;charset=utf8', DB_HOST, DB_NAME);
$pdo = new PDO($dsn, DB_USER, DB_PASS);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
} catch (PDOException $e) {
// 记录日志而不是直接暴露错误给用户
error_log("数据库连接失败: " . $e->getMessage());
throw new Exception("系统维护中,请稍后重试");
}
}
2. 用户模型(app/Models/User.php)
<?php
namespace App\Models;
use PDO;
use Exception;
class User
{
private $pdo;
// 依赖注入连接,方便测试
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
// 方法名清晰描述行为
public function create_user(array $user_data): int
{
// 参数验证
if (empty($user_data['email']) || empty($user_data['password'])) {
throw new Exception("邮箱和密码必填");
}
// SQL用参数绑定防注入
$sql = "INSERT INTO users (email, password_hash, created_at)
VALUES (:email, :password_hash, NOW())";
$stmt = $this->pdo->prepare($sql);
// 密码哈希存储(千万别明文!)
$hashed_password = password_hash($user_data['password'], PASSWORD_DEFAULT);
$stmt->execute([
':email' => $user_data['email'],
':password_hash' => $hashed_password
]);
return (int)$this->pdo->lastInsertId();
}
// 查找用户:返回类型声明(PHP7+特性)
public function find_user_by_email(string $email): ?array
{
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute([':email' => $email]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
return $result ?: null; // 清晰的三元表达式
}
}
3. 日志服务(app/Services/LoggerService.php)
<?php
namespace App\Services;
class LoggerService
{
// 用常量定义日志级别
const LEVEL_ERROR = 'ERROR';
const LEVEL_INFO = 'INFO';
private $log_file;
public function __construct(string $log_file_path)
{
// 确保日志目录存在
$dir = dirname($log_file_path);
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
$this->log_file = $log_file_path;
}
// 格式化日志信息,包含时间戳和级别
public function log(string $message, string $level = self::LEVEL_INFO): void
{
$timestamp = date('Y-m-d H:i:s');
$log_entry = sprintf("[%s] %s: %s\n", $timestamp, $level, $message);
// 文件追加写入,LOCK_EX防止并发写入混乱
file_put_contents($this->log_file, $log_entry, FILE_APPEND | LOCK_EX);
}
}
4. 主入口文件(public/index.php)
<?php
// 统一入口,初始化设置
error_reporting(E_ALL);
ini_set('display_errors', '0'); // 生产环境不显示错误给用户
ini_set('log_errors', '1');
// 自动加载(简单版示例,实际建议用Composer)
spl_autoload_register(function ($class_name) {
$file = __DIR__ . '/../app/' . str_replace('\\', '/', $class_name) . '.php';
if (file_exists($file)) {
require_once $file;
}
});
// 处理用户注册请求
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
try {
// 1. 获取配置
require_once __DIR__ . '/../config/database.php';
// 2. 初始化服务和模型
$pdo = get_db_connection();
$user_model = new App\Models\User($pdo);
$logger = new App\Services\LoggerService(__DIR__ . '/../logs/app.log');
// 3. 业务逻辑
if ($_POST['action'] === 'register') {
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$password = $_POST['password'] ?? '';
if (!$email || strlen($password) < 6) {
throw new Exception("邮箱无效或密码太短");
}
// 检查用户是否已存在
if ($user_model->find_user_by_email($email)) {
throw new Exception("该邮箱已注册");
}
// 创建用户
$user_id = $user_model->create_user([
'email' => $email,
'password' => $password
]);
// 记录成功日志
$logger->log("用户注册成功: ID={$user_id}, Email={$email}");
echo json_encode([
'success' => true,
'message' => '注册成功,请登录'
]);
}
} catch (Exception $e) {
// 统一错误处理
if (isset($logger)) {
$logger->log("注册失败: " . $e->getMessage(), LoggerService::LEVEL_ERROR);
}
http_response_code(400);
echo json_encode([
'success' => false,
'message' => $e->getMessage()
]);
}
} else {
// 显示注册表单(前端部分简化)
?>
<!DOCTYPE html>
<html>
<head>
<title>用户注册示例</title>
<style>
body { font-family: Arial; max-width: 400px; margin: 50px auto; }
input { display: block; margin: 10px 0; padding: 8px; width: 100%; }
button { background: #007bff; color: white; padding: 10px; border: none; }
</style>
</head>
<body>
<h2>注册体验规范代码</h2>
<form method="POST">
<input type="email" name="email" placeholder="邮箱" required>
<input type="password" name="password" placeholder="密码(至少6位)" required>
<input type="hidden" name="action" value="register">
<button type="submit">提交</button>
</form>
<script>
// 简单前端验证
document.querySelector('form').addEventListener('submit', function(e) {
const password = this.querySelector('[name="password"]').value;
if (password.length < 6) {
alert('密码太短啦!');
e.preventDefault();
}
});
</script>
</body>
</html>
<?php
}
四、规范带来的实际好处:算笔经济账
假设你团队有5个PHP程序员:
- 不规范时:每人每天多花1小时读/改混乱代码,每月多加班20小时,时薪100元 → 每月浪费5×20×100=10,000元
- 规范后:代码可读性提升,新人上手快,合并冲突减少 → 省下的时间起码价值8,000元/月
更重要的是:代码质量高,线上bug少,半夜报警少,头发掉得少,老婆吵架少!
五、快速上手指南:工具推荐
- PHP_CodeSniffer:自动检查代码规范
composer require squizlabs/php_codesniffer
phpcs --standard=PSR12 app/
- PHP-CS-Fixer:自动修复不规范代码
composer require friendsofphp/php-cs-fixer
php-cs-fixer fix app/
- IDE配置:
-
- PHPStorm:开启PSR1/PSR2检查
- VSCode:安装PHP Intelephense插件
最后说句大实话
编码规范就像刷牙——开始时觉得麻烦,习惯了就自然。不规范的代码短期内似乎写得快,但长期看是在给自己挖坑,迟早要跪着填。
记住:好程序员不止让代码能跑,还要让代码能“活”——活得久、活得稳、活得让别人接手时不想打你。
(完整示例代码已测试可运行,GitHub仓库地址私信我获取,避免广告嫌疑😂)
附录:常见QA
Q:规范太多记不住怎么办?
A:用工具自动检查!先掌握最核心的命名、缩进、注释三条,其他慢慢养成习惯。
Q:老项目代码一团乱,要不要重写?
A:别!用“逐步重构法”,新代码按规范写,旧代码在修改时顺手整理,像打扫房间一样慢慢来。
Q:团队有人不遵守怎么办?
A:代码审查时“温柔拒绝合并”,附上本文链接(暗示他该学习了😉)。
2万+

被折叠的 条评论
为什么被折叠?



