
Coolify 仓库中的 Laravel 最佳实践技能19 类规则体系与源码印证指南【免费下载链接】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/coolifyCoolify 是一个基于 Laravel 构建的开源自托管 PaaS其仓库中内置了一套完整的 AI 辅助开发技能文件 .agents/skills/laravel-best-practices/SKILL.md系统性地总结了 19 大类 Laravel 后端最佳实践。读完本文你将掌握这套按影响力排序的规则体系——包括数据库 N1 治理、队列重试与锁机制、缓存分层策略、安全边界与任务调度的完整要点并能看到 Coolify 仓库自身的配置与 Job 实现如何印证这些规则。一、技能文件结构与一致性优先原则这份技能文件的 frontmatter 声明了触发条件凡涉及控制器、模型、迁移、Form Request、Policy、Job、定时命令、Service 类的编写、审查或重构均适用该技能。其正文结构分为三部分Consistency First一致性优先应用任何规则之前先检查代码库已有的做法。Laravel 往往存在多种合法写法——最佳选择是代码库已经采用的那一种即使另一种模式理论上更优。不一致性比次优模式更糟。因此这些规则是尚无可循模式时的默认值而非推翻既有约定的强制覆盖。Quick Reference快速参考19 类规则目录每类都链接到 rules/ 目录下的详细规则文件并附要点清单。How to Apply应用方法按文件类型选取相关章节如迁移 → §16、控制器 → §1/§3/§5/§6/§10、先查兄弟文件的既有模式、再按已安装版本核对 API 语法。下表是该快速参考目录的完整映射已转换为仓库根目录相对路径编号主题规则文件1数据库性能db-performance.md2高级查询模式advanced-queries.md3安全security.md4缓存caching.md5Eloquent 模式eloquent.md6验证与表单validation.md7配置config.md8测试模式testing.md9队列与 Jobqueue-jobs.md10路由与控制器routing.md11HTTP Clienthttp-client.md12事件、通知与邮件events-notifications.md、mail.md13错误处理error-handling.md14任务调度scheduling.md15架构architecture.md16迁移migrations.md17集合collections.md18Blade 与视图blade-views.md19约定与风格style.md二、数据库性能N1 治理与批量处理§1db-performance.md 是 19 类规则中第一条也是 Coolify 这类管理面板类项目最直接影响响应时间的领域。核心要点包括2.1 始终使用with()预加载关系懒加载在循环中触发 N1 查询1 条主查询 N 条关系查询。正确写法是一次预加载总共只执行 2 条查询// 错误N1执行 1 N 条查询 $posts Post::all(); foreach ($posts as $post) { echo $post-author-name; } // 正确共 2 条查询 $posts Post::with(author)-get(); foreach ($posts as $post) { echo $post-author-name; }预加载时还可约束约束条件只选择需要的列——务必包含外键列否则关系无法匹配$users User::with([posts function ($query) { $query-select(id, user_id, title) -where(published, true) -latest() -limit(10); }])-get();2.2 开发环境开启懒加载防护在AppServiceProvider::boot()中启用以下代码开发阶段访问未预加载关系时抛出LazyLoadingViolationException让 N1 在开发期即被暴露public function boot(): void { Model::preventLazyLoading(! app()-isProduction()); }2.3 分块处理与游标迭代批量处理绝不::all()加载数千条记录用chunk(200, ...)迭代中修改/删除记录时必须用chunkById()——普通chunk()基于 OFFSET行变动后会发生偏移漏处理User::where(active, false)-chunkById(200, function ($users) { $users-each-delete(); });只读大结果集迭代用cursor()PHP generator 逐条读取内存高效计数关系用withCount()而非加载整个集合再-count()条件计数写法$posts Post::withCount([ comments, comments as approved_comments_count function ($query) { $query-where(approved, true); }, ])-get();Blade 模板中禁止执行查询——数据一律从控制器传入。2.4 索引策略对出现在WHERE、ORDER BY、JOIN、GROUP BY中的列建索引对常见查询模式如WHERE status ? ORDER BY created_at建复合索引。Coolify 自己的数据库迁移遵循同样思路大量外键使用foreignId(...)-constrained()自动建索引例如 2023_03_24_140711_create_servers_table.php。三、高级查询模式§2advanced-queries.md 提供了 8 个进阶技巧解决预加载整个 has-many 只为取一个值这类低效模式addSelect()相关子查询为 has-many 关系取单值如最近登录时间时直接注入主查询零额外查询并可用withCasts()附带类型转换子查询 FK 虚拟belongsTo先用子查询取last_login_id再在模型上定义belongsTo获得完全水合的关联模型而非整个集合条件聚合替代多次 countselectRaw(count(case when status X then 1 end))一条查询完成 N 个状态计数toBase()跳过模型水合setRelation()打断循环 N1父模型已随子集合加载后$children-each-setRelation(parent, $parent)阻止 Eloquent 再发 N 条查询whereIn 子查询优于whereHaswhereHas发出逐行重执行的关联EXISTS子查询而whereIn(company_id, Company::where(...)-select(id))允许数据库走索引查找两条简单查询可胜一条复杂查询当二级查询高选择性且有独立索引时多一次往返是划算的复合索引列序须与ORDER BY一致——单列索引无法组合用于多列排序数据库只能 filesorthas-many 排序用相关子查询而非 joinjoin 会复制行public function scopeOrderByLastLogin($query): void { $query-orderByDesc(Login::select(created_at) -whereColumn(user_id, users.id) -latest() -take(1) ); }四、安全规则§3security.md 覆盖了 9 个安全主题每条都可直接作为代码评审检查项批量赋值防护每个模型必须定义$fillable或$guarded接受用户输入的模型禁用$guarded []每次操作都授权控制器中用Gate::authorize(update, $post)或在 Form Request 的authorize()方法中$this-user()-can(update, $this-route(post))。Coolify 的 app/Policies/ 目录实现了 27 个 Policy 类如 ApplicationPolicy.php、ServerPolicy.php正是该规则在真实项目中的落地形态防 SQL 注入只用参数绑定User::whereRaw(LOWER(name) ?, [strtolower($request-name)])防 XSS输出用{{ }}{!! !!}仅限可信的、已净化的内容CSRF所有 POST/PUT/DELETE 的 Blade 表单包含csrfInertia 应用自动处理限流认证与 API 路由套throttleRateLimiter::for(login, fn (Request $request) Limit::perMinute(5)-by($request-ip()))文件上传校验mimes查扩展名、mimetypes查真实 MIME、max限制大小存储时用生成的文件名密钥管理.env绝不入库应用代码中只通过config()访问密钥env()仅允许出现在 config 文件中敏感字段加密API key/token 用encryptedcast 并标记hidden同时建议 CI 中定期执行composer audit。Coolify 的 EncryptedArrayCast.php 与私钥加密迁移2024_09_16_111428_encrypt_existing_private_keys.php说明项目本身也在落实这一条。五、缓存分层策略§4caching.md 给出了一套从请求内到跨请求的缓存层次API适用场景关键行为Cache::remember()通用 cache-aside替代手工 get/put 样板代码Cache::flexible(key, [300, 600], fn)高流量键的 stale-while-revalidate5 分钟内新鲜最长 10 分钟提供稍旧数据后台刷新避免缓存击穿时某用户必然慢响应Cache::memo()单请求内重复读同一键内存驻留5 次调用 1 次 Redis 往返Cache tags成组失效Cache::tags([user-1])-flush()仅redis/memcached/dynamodb驱动支持Cache::add()原子条件写仅当键不存在时写入消除检查-写入竞态once()纯内存的每请求/每对象记忆化完全不触碰缓存存储Cache::lock()/lockForUpdate()竞态条件分布式锁Failover store生产环境failover [driver failover, stores [redis, database]]Redis 宕机自动降级once()与Cache::memo()的选型口诀只做昂贵计算的一次性缓存用once()既想跨请求又想减少往返用Cache::memo()。六、队列与 JobCoolify 配置中的实证§9queue-jobs.md 的规则与 Coolify 仓库的实际配置高度呼应是本文最适合规则—源码互证的一节。规则要点retry_after必须大于 Job 的timeout否则 worker 会在任务仍在运行时重新派发造成重复执行重试间隔用指数退避$backoff [1, 5, 10]ShouldBeUnique防重复处理uniqueId()返回业务唯一键ShouldBeUniqueUntilProcessing则在处理开始时即释放锁允许新实例入队必须实现failed()显式处理终态失败不能静默丢失使用retryUntil()做时间上限重试时必须设$tries 0调用第三方 API 的 Job 套RateLimited中间件相关 Job 用Bus::batch()整体成败。Coolify 中的印证app/Jobs/CleanupHelperContainersJob.php 声明了implements ShouldBeEncrypted, ShouldBeUnique, ShouldQueue——一个同时加密载荷、防重复执行的清理 Job正是规则中ShouldBeUnique的典型应用场景同类还有 CleanupInstanceStuffsJob.php 等config/queue.php 中database与beanstalkd连接均为retry_after 90而redis连接为retry_after 86400——不同驱动下该参数按最长 Job 运行时长取值体现了retry_after 任何 timeout的约束项目启用了 Horizonconfig/horizon.php 定义了 supervisormaxProcesses由HORIZON_MAX_PROCESSES默认 4控制并配有balance/balanceMaxShift/balanceCooldown自动扩缩参数对应规则中复杂多队列场景用 Horizon的建议。七、Eloquent、验证、路由三条高频规则线§5/§6/§107.1 Eloquent 模式eloquent.md 的要点关系方法带正确返回类型提示public function comments(): HasMany可复用约束提取为 local scopescopeActive全局 scope 仅限软删除、多租户等普适约束且必须记录其存在属性类型转换集中在casts()方法中日期列必须 cast 为datetime模板直接用 Carbon 实例而非手工格式化Post::whereBelongsTo($user)替代手写下划线外键查询中禁止硬编码表名字符串——必须用(new User)-getTable()迁移文件是唯一例外迁移是冻结快照引用日后可能被重命名的模型反而会坏掉。7.2 验证与表单validation.md 五条规则校验逻辑从控制器抽到 Form Request 类新代码优先数组语法[required, email]但先遵循项目既有风格只允许$request-validated()绝不用$request-all()做批量赋值条件校验用Rule::when()跨字段自定义校验用after()方法返回闭包数组而非withValidator()。Coolify 中对应的实践可见 app/Rules/ 下的 12 个自定义验证规则如 DockerImageFormat.php、SafeWebhookUrl.php。7.3 路由与控制器routing.md隐式路由模型绑定public function show(Post $post)取代findOrFail嵌套资源用-scopeBindings()强制父子从属RESTful 端点用Route::resource()/apiResource()控制器方法保持 10 行以内业务逻辑抽到 Action/Service 类Form Request 类型提示会在方法执行前自动触发验证与授权。Coolify 的路由层即按此组织routes/api.php、routes/web.php 分别承载 API 与 Web 入口控制器集中在 app/Http/Controllers/48 个控制器文件。八、HTTP Client 与任务调度§11/§148.1 HTTP Clienthttp-client.md 对每个出站请求的要求显式超时默认 30 秒对多数 API 调用太长Http::timeout(5)-connectTimeout(3)快速失败服务级客户端用 macro 固化配置指数退避重试Http::retry([100, 500, 1000])或仅对连接异常/5xx 重试显式错误处理HTTP Client 默认不抛 4xx/5xx用-throw()或手动检查successful()/notFound()Http::pool()并发独立请求三个接口并行发出而非串行测试中Http::fake()preventStrayRequests()禁止真实出站并覆盖Http::failedConnection()失败场景。8.2 任务调度scheduling.md 六条规则时长不定的任务加withoutOverlapping()防止同任务双开多服务器部署加onOneServer()依赖共享缓存驱动runInBackground()让同 tick 的慢任务不阻塞后续任务environments([production])防止生产专用任务计费、报表在 staging 误跑takeUntilTimeout()给处理无界游标的任务设时间上界重复的-onOneServer()-timezone(...)配置收敛到Schedule::daily()-group(...)调度分组。九、其余规则要点与应用方法Quick Reference 中还覆盖以下主题各自在 rules/ 目录下有独立细则配置§7env()只出现在 config 文件中环境判断用App::environment()/app()-isProduction()文案走 config、语言包或常量不硬编码。Coolify 的 config/ 目录含 30 余个配置文件app.php、queue.php、horizon.php 等env()调用均收敛其中测试模式§8LazilyRefreshDatabase优于RefreshDatabase、assertModelExists()、工厂 state/sequence、fake 类Event::fake()等须在工厂数据准备之后调用、recycle()共享关联实例。Coolify 的测试体系位于 tests/Pest 框架Feature 测试 500 个文件架构§15单一职责的 Action 类、依赖注入优先于app()helper、默认ORDER BY id DESC或created_at DESC、UTF-8 安全用mb_*函数、defer()处理响应后工作、Context存请求级数据、Concurrency::run()并行执行迁移§16php artisan make:migration生成、constrained()建外键、绝不修改已上生产的迁移、索引随迁移加入而非事后补、列默认值与模型$attributes镜像一致、down()默认可逆故意不可逆的变更用前向修复迁移、一个迁移只处理一件事——绝不混 DDL 与 DML集合§17高阶消息处理简单集合操作、按是否需要关系在cursor()与lazy()间选择、迭代中更新记录用lazyById()、批量操作用toQuery()Blade 与视图§18组件模板中$attributes-merge()、Blade 组件优于include、pushOnce管理按组件脚本、View Composer 共享视图数据、aware传递深层组件 props风格§19遵循 Laravel 命名约定、优先Str/Arr/Number/Uri/Str::of()等官方 helper 而非裸 PHP 函数、Blade 中不写 JS/CSS、PHP 类中不嵌 HTML。应用方法来自 SKILL.md 末尾识别文件类型后只选取相关章节迁移 → §16控制器 → §1、§3、§5、§6、§10先查兄弟文件的既有模式并按一致性优先遵循最后按已安装的 Laravel 版本核对确切 API 语法。十、结语把规则体系落到代码库这份技能文件的价值在于两点一是按影响力而非字母序组织 19 类规则每条都给出做什么 为什么的正反例二是它明确自身定位为无既有模式时的默认值避免与真实代码库的既有约定冲突。对 Coolify 这样的 Laravel 项目而言config/queue.php 中分驱动的retry_after设置、config/horizon.php 的 supervisor 自动扩缩、Job 类上的ShouldBeUnique实现都是规则与工程实践相互印证的直接证据——读者可以沿文中路径对照仓库源码把这套规则用作评审清单或重构依据。【免费下载链接】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),仅供参考