Coolify 的 Laravel 代码风格规范:命名约定、短语法与 Helpers 实战指南
【免费下载链接】coolifyAn open-source, self-hostable PaaS alternative to Vercel, Heroku & Netlify that lets you easily deploy static sites, databases, full-stack applications and 280+ one-click services on your own servers.项目地址: https://gitcode.com/GitHub_Trending/co/coolify
本文以 Coolify 仓库内置的 Laravel 风格规范 style.md 为核心,系统讲解 Laravel 代码风格约定——从命名规范、精简语法到Str/Arr/Number/Uri等 Helpers 的优先使用,并结合 Coolify 自身源码逐一印证。读完本文,你将掌握一套可直接用于 Laravel 编码、代码评审与重构的检查清单,并能理解 Coolify 实际代码中如何体现(或有意偏离)这些约定。
一、这份风格规范在项目中的位置
style.md 属于 Coolify 仓库内laravel-best-practicesskill 的 19 份规则文件之一(对应快速参考中的§19 Conventions & Style)。该 skill 的入口 SKILL.md 明确它的适用范围:编写、评审或重构任何 Laravel PHP 代码——控制器、模型、迁移、Form Request、Policy、Job、命令行任务、Service 类与 Eloquent 查询——都要优先套用这些规则。
需要特别指出的是,style 规则并非"一刀切"的硬性标准。SKILL.md 在开篇给出了一个前提——Consistency First(一致性优先):
Laravel 允许多种同样合理的写法,最佳选择永远是当前代码库已经在用的那一种;不一致比次优的模式更糟糕。在引入新写法前,先看兄弟文件、相关控制器、模型或测试里已确立的模式,如果没有既定模式,再把这些规则当作默认值。
因此,阅读本文时请牢记:下表约定是"无既定模式时的默认值",而非必须推翻现有代码的依据。
二、严格遵循 Laravel 命名约定
风格规范的第一大主题是命名。原文用一张对照表给出了各层构件(构件 → 约定 → 好例 → 坏例),这里逐条展开,并结合 Coolify 实际代码给出佐证。
| 构件 | 约定 | 好例 | 坏例 | 语义说明 |
|---|---|---|---|---|
| Controller | 单数 | ArticleController | ArticlesController | 一个控制器管理一类资源的单个概念 |
| Model | 单数 | User | Users | 模型类代表"一条/一类实体" |
| Table | 复数、snake_case | article_comments | articleComments | 表存多行数据,习惯用复数名词 |
| Pivot table | 单数、按字母序 | article_user | user_article | 中间表由两个单数实体名按字母序拼接 |
| Column | snake_case、不含模型名 | meta_title | article_meta_title | 列名只描述属性本身 |
| Foreign key | 单数模型名 +_id | article_id | articles_id | 外键指向"单个"父模型 |
| Route | 复数 | articles/1 | article/1 | URL 中的资源名用复数 |
| Route name | snake_case + 点号 | users.show_active | users.show-active | 用.分隔层级,用_分隔单词 |
| Method | camelCase | getAll | get_all | PHP 方法一律驼峰 |
| Variable | camelCase | $articlesWithAuthor | $articles_with_author | PHP 变量驼峰 |
| Collection | 描述性、复数 | $activeUsers | $data | 集合是"一堆东西" |
| Object | 描述性、单数 | $activeUser | $users | 对象是"一个东西" |
| View | kebab-case | show-filtered.blade.php | showFiltered.blade.php | Blade 文件名用连字符小写 |
| Config | snake_case | google_calendar.php | googleCalendar.php | 配置文件用下划线命名 |
| Enum | 单数 | UserType | UserTypes | 枚举类用单数名词 |
2.1 Model 与 Table:Coolify 的标准示范
Coolify 的模型目录与迁移文件基本完全符合上表。以 app/Models 为例,模型类全部单数:Application、ApplicationDeploymentQueue、Environment、Project、Server、Team、User等;对应的迁移表名全部为复数 snake_case,例如:
- create_users_table.php → 表
users - create_teams_table.php → 表
teams - create_servers_table.php → 表
servers - create_projects_table.php → 表
projects - create_applications_table.php → 表
applications
2.2 Pivot 表与外键:字母序拼接 +_id后缀
Coolify 的团队-用户多对多关系是命名约定的最佳样本。迁移文件 create_team_user_table.php 创建的中间表名team_user正是两个单数实体名按字母序拼接(team<user);且其外键列完全符合"单数模型名 +_id"约定:
$table->foreignId('team_id'); $table->foreignId('user_id'); $table->unique(['team_id', 'user_id']);2.3 一致性优先:仓库中的"例外"也值得注意
对照上表审视 Coolify 源码,可以发现两处既有模式与规范默认值不一致,恰好印证了 SKILL.md 的 Consistency First 原则:
- API 资源控制器使用复数命名:例如 Api/ApplicationsController.php、Api/CloudInitScriptsController.php、Api/DatabasesController.php。而 Web 侧控制器大多符合单数约定,如
OauthController、ProjectIconController、UploadController、DeployController。这是既有模式与新代码默认值冲突的典型例子——在Api命名空间内继续沿用复数,远比强行重命名要合理。 - 枚举类使用复数:Coolify 的枚举文件集中放在 app/Enums,如
ActivityTypes、BuildPackTypes、ContainerStatusTypes、ApplicationDeploymentStatus,而规范表建议单数(UserType)。由于枚举目录内的既有模式就是复数形式,按一致性原则应当继续沿用。
文章生成后的仓库内新增枚举(例如仿照 BuildPackTypes.php 建立新枚举)时,也应先观察目录内已有写法再决定是*Type还是*Types。
2.4 Blade 视图命名:kebab-case 无处不在
规范要求视图文件使用 kebab-case。Coolify 的 resources/views 目录严格执行了这一约定,例如组件文件copy-button.blade.php、env-var-input.blade.php、breadcrumb-switcher.blade.php、configuration-sidebar.blade.php等,全部是小写字母加连字符的命名方式。
2.5 方法与变量:camelCase
Coolify 源码中的方法命名遵循 camelCase。例如 Services/ChangelogService.php 中的getAllEntries()、hasUnread()等公开方法;Eloquent 关系方法同样驼峰命名。控制器与 Service 中的局部变量也统一使用$this->server、$resourceUuid这类驼峰风格。
三、优先使用更短的可读语法
原文档第二张表给出了一批"啰嗦写法 → 简短写法"的对齐关系。核心理念是:Laravel 提供的全局函数和链式 API 语义与Facade/Request等价,但更短、更可读、不易出错。
| 啰嗦写法 | 简短写法 |
|---|---|
Session::get('cart') | session('cart') |
$request->session()->get('cart') | session('cart') |
$request->input('name') | $request->name |
return Redirect::back() | return back() |
Carbon::now() | now() |
App::make('Class') | app('Class') |
->where('column', '=', 1) | ->where('column', 1) |
->orderBy('created_at', 'desc') | ->latest() |
->orderBy('created_at', 'asc') | ->oldest() |
->first()->name | ->value('name') |
3.1 仓库实测:短语法如何落地
session()替代Session::get():Coolify 在 app/Livewire/Admin/Index.php 使用session('impersonating')读取会话数据,而不是Session::get('impersonating')。->latest()替代->orderBy('created_at', 'desc'):这一用法在 Livewire 组件中大量出现。例如 app/Livewire/Project/Application/Backup/Index.php 直接链式调用->latest()拉取备份列表;app/Livewire/Security/ApiTokens.php、app/Livewire/Project/Service/VolumeBackup/Index.php 等同样如此。->value('column')替代->first()->column:app/Actions/Team/DeleteTeam.php 在判断当前成员角色时使用->value('role')直接取单列标量,避免了先取整个模型再取属性的两步写法。
这套短语法还可以和 Eloquent 全局作用域、本地作用域自由组合,例如在列表页中先where()再->latest()就能稳定得到"时间倒序"的新数据在前效果。
四、使用 Laravel 字符串与数组 Helpers
规范明确指出:Laravel 提供的Str、Arr、Number、Uri帮助类比裸 PHP 函数更可读、可链式调用,且天然 UTF-8 安全,应始终优先使用。
4.1 字符串:优先Str与流式Str::of()
原文档强调,不要使用strtolower、substr、strrchr等裸函数拼凑字符串处理逻辑:
// Incorrect —— 裸 PHP 函数拼接,难读且多字节不安全 $slug = strtolower(str_replace(' ', '-', $title)); $short = substr($text, 0, 100) . '...'; $class = substr(strrchr('App\Models\User', '\'), 1); // Correct —— Laravel 帮助类 $slug = Str::slug($title); $short = Str::limit($text, 100); $class = class_basename('App\Models\User');对于复杂变换,用流式字符串(fluent string)逐段链式表达意图:
// Incorrect $result = strtolower(trim(str_replace('_', '-', $input))); // Correct $result = Str::of($input)->trim()->replace('_', '-')->lower();Coolify 在 app/Jobs/ApplicationDeploymentJob.php 中就有流式字符串处理 commit 的实际用例——清理非法字符、截断并转回字符串:
$commit = Str::of($commitSource) ->replaceMatches('/[^A-Za-z0-9_.-]/', '-') ->substr(0, $maxCommitLength) ->toString();类似的str($value)流式用法还出现在 app/Actions/Proxy/CheckProxy.php(str($port)->before(':')->value())、app/Models/LocalPersistentVolume.php(Str::slug($source, '-')生成卷名)等位置。
文档给出的常用Str方法清单如下,可直接作为编码速查:Str::slug()、Str::limit()、Str::contains()、Str::before()、Str::after()、Str::between()、Str::camel()、Str::snake()、Str::kebab()、Str::headline()、Str::squish()、Str::mask()、Str::uuid()、Str::ulid()、Str::random()、Str::is()。如需完整清单,可借助search-docs检索当前 Laravel 版本支持的 API。
4.2 数组:优先Arr
用Arr代替isset三元链,取值表达式更加线性:
// Incorrect $name = isset($array['user']['name']) ? $array['user']['name'] : 'default'; // Correct —— 支持点号路径与默认值 $name = Arr::get($array, 'user.name', 'default');常用Arr方法包括:Arr::get()、Arr::has()、Arr::only()、Arr::except()、Arr::first()、Arr::flatten()、Arr::pluck()、Arr::where()、Arr::wrap()。
4.3 数字:优先Number做显示格式化
涉及展示层的数字格式化使用Number,避免手写千分位/货币/文件大小逻辑:
Number::format(1000000); // "1,000,000" Number::currency(1500, 'USD'); // "$1,500.00" Number::abbreviate(1000000); // "1M" Number::fileSize(1024 * 1024); // "1 MB" Number::percentage(75.5); // "75.5%"4.4 URI:优先Uri操作 URL
构建带查询参数的 URL 使用Uri,比手工拼字符串更稳健:
$uri = Uri::of('https://example.com/search') ->withQuery(['q' => 'laravel', 'page' => 1]);4.5 Request 输入直接转流式字符串
当需要立即对表单输入做链式处理时,用$request->string('name')直接拿到流式Stringable,不必再手动包一层Str::of():
$title = $request->string('title')->trim()->title();五、Blade 中禁止内联 JS/CSS
第三大主题是关注点分离:不在 Blade 模板里塞<script>/<style>,也不在 PHP 类里输出 HTML。数据需要交给 JavaScript 时,通过data 属性或@json/@js指令传递,而不是把json_encode($article)直接拼进模板:
{{-- Incorrect: 在 JS 里内联插值 --}} let article = `{{ json_encode($article) }}`; {{-- Correct: data 属性 + @json,安全转义 --}} <button class="js-fav-article">// Incorrect: 注释解释"这段代码在做什么" // Check if there are any joins if (count((array) $builder->getQuery()->joins) > 0) // Correct: 方法名本身就是文档 if ($this->hasJoins())唯一的例外是配置文件——Coolify 的 config 目录(如 config/constants.php、config/horizon.php 等)保留了大量说明性注释,这正是规范所鼓励的"配置文件里可以有详细注释"。
七、风格规范在 Coolify 中的落地工具
代码风格最终要靠工具固化,而不是靠人工评审记忆。Coolify 的工程配置为 Laravel 风格规范提供了三层兜底:
- Laravel Pint(代码风格修复器):
composer.json的 require-dev 中声明了laravel/pint: ^1.30.4,项目根目录的 pint.json 定义了规则集。写完后运行./vendor/bin/pint即可自动统一格式。 - Rector:require-dev 中声明了
rector/rector与driftingly/rector-laravel,配合 rector.php 做自动化重构。 - 测试与静态分析:项目使用 Pest(
pestphp/pest: ^4)与 PHPStan(phpstan/phpstan: ^2.2),相关用例见 tests 目录;在 IDE 中开启这些检查可以在提交前提前暴露命名与类型问题。
结语:一份可复用的 Laravel 代码风格自检清单
结合 style.md 与 SKILL.md 的 Consistency First 原则,参与 Coolify 或任何 Laravel 项目的编码/评审时可按下述清单逐项自检:
- 命名:Controller/Model 单数、Table 复数 snake_case、Pivot 表按字母序拼接、外键为
模型名_id、Blade 视图 kebab-case、方法与变量 camelCase; - 语法:能用
session()、back()、now()、->latest()、->value()就不写冗长的 Facade/链式调用; - Helpers:字符串/数组/数字/URI 操作优先
Str/Arr/Number/Uri,避免裸 PHP 函数; - Blade:不写内联 JS/CSS,数据经
@js/@json/data 属性传入,HTML 不进 PHP 类; - 注释:代码以"方法名即文档"为主,注释仅保留给配置文件;
- 一致性:新代码先看相邻文件已确立的模式;改动大范围历史代码前,与仓库既有风格保持一致优先于理论最优。
其余主题(Eloquent 查询、缓存、队列、安全、测试等)的配套规则见同一 skill 的 architecture.md、eloquent.md、routing.md 等兄弟文件,可在对应场景继续深入查阅。
【免费下载链接】coolifyAn open-source, self-hostable PaaS alternative to Vercel, Heroku & Netlify that lets you easily deploy static sites, databases, full-stack applications and 280+ one-click services on your own servers.项目地址: https://gitcode.com/GitHub_Trending/co/coolify
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考