@mohammadhprp/system-prompt 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +35 -0
- package/bin/system-prompt.js +8 -0
- package/framework/README.md +163 -0
- package/framework/agents/README.md +49 -0
- package/framework/agents/backend-architect.md +146 -0
- package/framework/agents/researcher.md +79 -0
- package/framework/agents/reviewer.md +183 -0
- package/framework/agents/security-auditor.md +131 -0
- package/framework/commands/README.md +43 -0
- package/framework/commands/changelog.md +44 -0
- package/framework/commands/commit.md +31 -0
- package/framework/commands/learn.md +24 -0
- package/framework/commands/mr.md +46 -0
- package/framework/commands/pr.md +39 -0
- package/framework/commands/release.md +34 -0
- package/framework/commands/review.md +24 -0
- package/framework/commands/summarize-changes.md +49 -0
- package/framework/mcps/README.md +78 -0
- package/framework/mcps/excalidraw/README.md +37 -0
- package/framework/mcps/excalidraw/capabilities.md +54 -0
- package/framework/mcps/excalidraw/configs/opencode.json +8 -0
- package/framework/mcps/excalidraw/install.md +92 -0
- package/framework/mcps/excalidraw/troubleshooting.md +67 -0
- package/framework/mcps/figma-mcp-go/README.md +51 -0
- package/framework/mcps/figma-mcp-go/capabilities.md +190 -0
- package/framework/mcps/figma-mcp-go/configs/opencode.json +9 -0
- package/framework/mcps/figma-mcp-go/install.md +74 -0
- package/framework/mcps/figma-mcp-go/troubleshooting.md +99 -0
- package/framework/mcps/github-mcp/README.md +51 -0
- package/framework/mcps/github-mcp/capabilities.md +83 -0
- package/framework/mcps/github-mcp/configs/.env.example +1 -0
- package/framework/mcps/github-mcp/configs/opencode.json +13 -0
- package/framework/mcps/github-mcp/install.md +60 -0
- package/framework/mcps/github-mcp/troubleshooting.md +79 -0
- package/framework/mcps/gitlab-mcp/README.md +54 -0
- package/framework/mcps/gitlab-mcp/capabilities.md +216 -0
- package/framework/mcps/gitlab-mcp/configs/.env.example +2 -0
- package/framework/mcps/gitlab-mcp/configs/opencode.json +13 -0
- package/framework/mcps/gitlab-mcp/install.md +99 -0
- package/framework/mcps/gitlab-mcp/troubleshooting.md +116 -0
- package/framework/mcps/jira-mcp/README.md +53 -0
- package/framework/mcps/jira-mcp/capabilities.md +79 -0
- package/framework/mcps/jira-mcp/configs/.env.example +2 -0
- package/framework/mcps/jira-mcp/configs/opencode.json +13 -0
- package/framework/mcps/jira-mcp/install.md +94 -0
- package/framework/mcps/jira-mcp/troubleshooting.md +113 -0
- package/framework/mcps/laravel-boost/README.md +53 -0
- package/framework/mcps/laravel-boost/capabilities.md +92 -0
- package/framework/mcps/laravel-boost/configs/opencode.json +9 -0
- package/framework/mcps/laravel-boost/install.md +106 -0
- package/framework/mcps/laravel-boost/troubleshooting.md +119 -0
- package/framework/mcps/notion-mcp/README.md +58 -0
- package/framework/mcps/notion-mcp/capabilities.md +118 -0
- package/framework/mcps/notion-mcp/configs/opencode.json +9 -0
- package/framework/mcps/notion-mcp/install.md +70 -0
- package/framework/mcps/notion-mcp/troubleshooting.md +95 -0
- package/framework/mcps/playwright-mcp/README.md +50 -0
- package/framework/mcps/playwright-mcp/capabilities.md +149 -0
- package/framework/mcps/playwright-mcp/configs/opencode.json +9 -0
- package/framework/mcps/playwright-mcp/install.md +136 -0
- package/framework/mcps/playwright-mcp/troubleshooting.md +154 -0
- package/framework/mcps/supabase-mcp/README.md +66 -0
- package/framework/mcps/supabase-mcp/capabilities.md +127 -0
- package/framework/mcps/supabase-mcp/configs/opencode.json +9 -0
- package/framework/mcps/supabase-mcp/install.md +85 -0
- package/framework/mcps/supabase-mcp/troubleshooting.md +113 -0
- package/framework/memory/README.md +17 -0
- package/framework/memory/codebase-insights.md +6 -0
- package/framework/memory/user-preferences.md +5 -0
- package/framework/modes/README.md +52 -0
- package/framework/modes/audit.md +88 -0
- package/framework/plugins/README.md +65 -0
- package/framework/plugins/opencode-goal-plugin/README.md +45 -0
- package/framework/plugins/opencode-goal-plugin/capabilities.md +127 -0
- package/framework/plugins/opencode-goal-plugin/install.md +71 -0
- package/framework/plugins/opencode-goal-plugin/troubleshooting.md +112 -0
- package/framework/plugins/ponytail/README.md +44 -0
- package/framework/plugins/ponytail/capabilities.md +112 -0
- package/framework/plugins/ponytail/install.md +77 -0
- package/framework/plugins/ponytail/troubleshooting.md +116 -0
- package/framework/references/standards/api.md +44 -0
- package/framework/references/standards/architecture.md +43 -0
- package/framework/references/standards/database.md +43 -0
- package/framework/references/standards/debugging.md +44 -0
- package/framework/references/standards/documentation.md +43 -0
- package/framework/references/standards/logging.md +43 -0
- package/framework/references/standards/naming.md +43 -0
- package/framework/references/standards/observability.md +43 -0
- package/framework/references/standards/performance.md +43 -0
- package/framework/references/standards/pull-requests.md +43 -0
- package/framework/references/standards/security.md +43 -0
- package/framework/references/standards/testing.md +43 -0
- package/framework/references/templates/adr.md +28 -0
- package/framework/references/templates/api-spec.md +56 -0
- package/framework/references/templates/design-document.md +39 -0
- package/framework/references/templates/incident-report.md +38 -0
- package/framework/references/templates/postmortem.md +41 -0
- package/framework/references/templates/pull-request.md +34 -0
- package/framework/references/templates/runbook.md +48 -0
- package/framework/references/templates/task.md +27 -0
- package/framework/skills/README.md +68 -0
- package/framework/skills/agent-browser/SKILL.md +51 -0
- package/framework/skills/backend-best-practices/SKILL.md +136 -0
- package/framework/skills/backend-best-practices/examples.md +31 -0
- package/framework/skills/backend-best-practices/references/api-design.md +79 -0
- package/framework/skills/backend-best-practices/references/architecture-review.md +77 -0
- package/framework/skills/backend-best-practices/references/database-design.md +78 -0
- package/framework/skills/backend-best-practices/references/debugging.md +76 -0
- package/framework/skills/backend-best-practices/references/observability.md +78 -0
- package/framework/skills/backend-best-practices/references/performance.md +78 -0
- package/framework/skills/backend-best-practices/references/refactoring.md +77 -0
- package/framework/skills/backend-best-practices/references/security.md +80 -0
- package/framework/skills/backend-best-practices/references/testing.md +77 -0
- package/framework/skills/backend-engineer/SKILL.md +76 -0
- package/framework/skills/backend-engineer/examples.md +31 -0
- package/framework/skills/brainstorming/SKILL.md +159 -0
- package/framework/skills/brainstorming/examples.md +49 -0
- package/framework/skills/brainstorming/scripts/frame-template.html +213 -0
- package/framework/skills/brainstorming/scripts/helper.js +167 -0
- package/framework/skills/brainstorming/scripts/server.cjs +723 -0
- package/framework/skills/brainstorming/scripts/start-server.sh +209 -0
- package/framework/skills/brainstorming/scripts/stop-server.sh +120 -0
- package/framework/skills/brainstorming/visual-companion.md +291 -0
- package/framework/skills/brand-guidelines/LICENSE.txt +202 -0
- package/framework/skills/brand-guidelines/SKILL.md +73 -0
- package/framework/skills/code-review/SKILL.md +72 -0
- package/framework/skills/code-review/examples.md +31 -0
- package/framework/skills/design/SKILL.md +399 -0
- package/framework/skills/design/examples.md +34 -0
- package/framework/skills/diagram-design/SKILL.md +485 -0
- package/framework/skills/diagram-design/assets/example-architecture-dark.html +180 -0
- package/framework/skills/diagram-design/assets/example-architecture-full.html +192 -0
- package/framework/skills/diagram-design/assets/example-architecture.html +181 -0
- package/framework/skills/diagram-design/assets/example-bar-dark.html +127 -0
- package/framework/skills/diagram-design/assets/example-bar-full.html +103 -0
- package/framework/skills/diagram-design/assets/example-bar.html +127 -0
- package/framework/skills/diagram-design/assets/example-data-flow-dark.html +143 -0
- package/framework/skills/diagram-design/assets/example-data-flow-full.html +185 -0
- package/framework/skills/diagram-design/assets/example-data-flow.html +143 -0
- package/framework/skills/diagram-design/assets/example-datalake-dark.html +241 -0
- package/framework/skills/diagram-design/assets/example-datalake-full.html +246 -0
- package/framework/skills/diagram-design/assets/example-datalake.html +267 -0
- package/framework/skills/diagram-design/assets/example-dp-integration-dark.html +78 -0
- package/framework/skills/diagram-design/assets/example-dp-integration-full.html +88 -0
- package/framework/skills/diagram-design/assets/example-dp-integration.html +78 -0
- package/framework/skills/diagram-design/assets/example-dp-security-matrix-dark.html +31 -0
- package/framework/skills/diagram-design/assets/example-dp-security-matrix-full.html +32 -0
- package/framework/skills/diagram-design/assets/example-dp-security-matrix.html +88 -0
- package/framework/skills/diagram-design/assets/example-er-dark.html +200 -0
- package/framework/skills/diagram-design/assets/example-er-full.html +203 -0
- package/framework/skills/diagram-design/assets/example-er.html +200 -0
- package/framework/skills/diagram-design/assets/example-flowchart-dark.html +154 -0
- package/framework/skills/diagram-design/assets/example-flowchart-full.html +157 -0
- package/framework/skills/diagram-design/assets/example-flowchart.html +154 -0
- package/framework/skills/diagram-design/assets/example-gantt-dark.html +135 -0
- package/framework/skills/diagram-design/assets/example-gantt-full.html +125 -0
- package/framework/skills/diagram-design/assets/example-gantt.html +135 -0
- package/framework/skills/diagram-design/assets/example-high-level-dark.html +249 -0
- package/framework/skills/diagram-design/assets/example-high-level-full.html +245 -0
- package/framework/skills/diagram-design/assets/example-high-level-vertical-dark.html +272 -0
- package/framework/skills/diagram-design/assets/example-high-level-vertical-full.html +250 -0
- package/framework/skills/diagram-design/assets/example-high-level-vertical.html +323 -0
- package/framework/skills/diagram-design/assets/example-high-level.html +299 -0
- package/framework/skills/diagram-design/assets/example-it-state-dark.html +90 -0
- package/framework/skills/diagram-design/assets/example-it-state-full.html +69 -0
- package/framework/skills/diagram-design/assets/example-it-state.html +128 -0
- package/framework/skills/diagram-design/assets/example-layers-dark.html +121 -0
- package/framework/skills/diagram-design/assets/example-layers-full.html +124 -0
- package/framework/skills/diagram-design/assets/example-layers.html +121 -0
- package/framework/skills/diagram-design/assets/example-line-dark.html +109 -0
- package/framework/skills/diagram-design/assets/example-line-full.html +103 -0
- package/framework/skills/diagram-design/assets/example-line.html +109 -0
- package/framework/skills/diagram-design/assets/example-loop-dark.html +100 -0
- package/framework/skills/diagram-design/assets/example-loop-full.html +137 -0
- package/framework/skills/diagram-design/assets/example-loop-terminal.html +347 -0
- package/framework/skills/diagram-design/assets/example-loop.html +100 -0
- package/framework/skills/diagram-design/assets/example-medallion-dark.html +159 -0
- package/framework/skills/diagram-design/assets/example-medallion-full.html +201 -0
- package/framework/skills/diagram-design/assets/example-medallion.html +159 -0
- package/framework/skills/diagram-design/assets/example-nested-dark.html +130 -0
- package/framework/skills/diagram-design/assets/example-nested-full.html +133 -0
- package/framework/skills/diagram-design/assets/example-nested.html +134 -0
- package/framework/skills/diagram-design/assets/example-org-chart-dark.html +45 -0
- package/framework/skills/diagram-design/assets/example-org-chart-full.html +45 -0
- package/framework/skills/diagram-design/assets/example-org-chart.html +45 -0
- package/framework/skills/diagram-design/assets/example-process-dark.html +62 -0
- package/framework/skills/diagram-design/assets/example-process-full.html +72 -0
- package/framework/skills/diagram-design/assets/example-process.html +62 -0
- package/framework/skills/diagram-design/assets/example-pyramid-dark.html +117 -0
- package/framework/skills/diagram-design/assets/example-pyramid-full.html +120 -0
- package/framework/skills/diagram-design/assets/example-pyramid.html +117 -0
- package/framework/skills/diagram-design/assets/example-quadrant-consultant.html +164 -0
- package/framework/skills/diagram-design/assets/example-quadrant-dark.html +133 -0
- package/framework/skills/diagram-design/assets/example-quadrant-full.html +136 -0
- package/framework/skills/diagram-design/assets/example-quadrant.html +133 -0
- package/framework/skills/diagram-design/assets/example-radar-dark.html +137 -0
- package/framework/skills/diagram-design/assets/example-radar-full.html +133 -0
- package/framework/skills/diagram-design/assets/example-radar.html +137 -0
- package/framework/skills/diagram-design/assets/example-scatter-dark.html +139 -0
- package/framework/skills/diagram-design/assets/example-scatter-full.html +114 -0
- package/framework/skills/diagram-design/assets/example-scatter.html +139 -0
- package/framework/skills/diagram-design/assets/example-sequence-dark.html +220 -0
- package/framework/skills/diagram-design/assets/example-sequence-full.html +386 -0
- package/framework/skills/diagram-design/assets/example-sequence.html +220 -0
- package/framework/skills/diagram-design/assets/example-state-dark.html +145 -0
- package/framework/skills/diagram-design/assets/example-state-full.html +148 -0
- package/framework/skills/diagram-design/assets/example-state.html +145 -0
- package/framework/skills/diagram-design/assets/example-swimlane-dark.html +170 -0
- package/framework/skills/diagram-design/assets/example-swimlane-full.html +173 -0
- package/framework/skills/diagram-design/assets/example-swimlane.html +170 -0
- package/framework/skills/diagram-design/assets/example-timeline-dark.html +133 -0
- package/framework/skills/diagram-design/assets/example-timeline-full.html +136 -0
- package/framework/skills/diagram-design/assets/example-timeline.html +133 -0
- package/framework/skills/diagram-design/assets/example-tree-dark.html +171 -0
- package/framework/skills/diagram-design/assets/example-tree-full.html +174 -0
- package/framework/skills/diagram-design/assets/example-tree.html +171 -0
- package/framework/skills/diagram-design/assets/example-venn-dark.html +130 -0
- package/framework/skills/diagram-design/assets/example-venn-full.html +133 -0
- package/framework/skills/diagram-design/assets/example-venn.html +108 -0
- package/framework/skills/diagram-design/assets/icons.html +230 -0
- package/framework/skills/diagram-design/assets/index.html +333 -0
- package/framework/skills/diagram-design/assets/template-dark.html +82 -0
- package/framework/skills/diagram-design/assets/template-full.html +410 -0
- package/framework/skills/diagram-design/assets/template-terminal.html +170 -0
- package/framework/skills/diagram-design/assets/template.html +83 -0
- package/framework/skills/diagram-design/references/export.md +107 -0
- package/framework/skills/diagram-design/references/onboarding.md +268 -0
- package/framework/skills/diagram-design/references/primitive-annotation.md +36 -0
- package/framework/skills/diagram-design/references/primitive-icons.md +821 -0
- package/framework/skills/diagram-design/references/primitive-sketchy.md +43 -0
- package/framework/skills/diagram-design/references/primitive-terminal.md +76 -0
- package/framework/skills/diagram-design/references/style-guide.md +139 -0
- package/framework/skills/diagram-design/references/type-architecture.md +78 -0
- package/framework/skills/diagram-design/references/type-bar.md +48 -0
- package/framework/skills/diagram-design/references/type-data-flow.md +374 -0
- package/framework/skills/diagram-design/references/type-dp-integration.md +410 -0
- package/framework/skills/diagram-design/references/type-dp-security-matrix.md +379 -0
- package/framework/skills/diagram-design/references/type-er.md +23 -0
- package/framework/skills/diagram-design/references/type-flowchart.md +23 -0
- package/framework/skills/diagram-design/references/type-gantt.md +45 -0
- package/framework/skills/diagram-design/references/type-high-level.md +458 -0
- package/framework/skills/diagram-design/references/type-it-state.md +470 -0
- package/framework/skills/diagram-design/references/type-layers.md +26 -0
- package/framework/skills/diagram-design/references/type-line.md +44 -0
- package/framework/skills/diagram-design/references/type-loop.md +223 -0
- package/framework/skills/diagram-design/references/type-medallion.md +356 -0
- package/framework/skills/diagram-design/references/type-nested.md +22 -0
- package/framework/skills/diagram-design/references/type-org-chart.md +44 -0
- package/framework/skills/diagram-design/references/type-process.md +495 -0
- package/framework/skills/diagram-design/references/type-pyramid.md +33 -0
- package/framework/skills/diagram-design/references/type-quadrant.md +81 -0
- package/framework/skills/diagram-design/references/type-radar.md +80 -0
- package/framework/skills/diagram-design/references/type-scatter.md +39 -0
- package/framework/skills/diagram-design/references/type-sequence.md +35 -0
- package/framework/skills/diagram-design/references/type-state.md +21 -0
- package/framework/skills/diagram-design/references/type-swimlane.md +20 -0
- package/framework/skills/diagram-design/references/type-timeline.md +20 -0
- package/framework/skills/diagram-design/references/type-tree.md +24 -0
- package/framework/skills/diagram-design/references/type-venn.md +26 -0
- package/framework/skills/documentation/SKILL.md +74 -0
- package/framework/skills/documentation/examples.md +31 -0
- package/framework/skills/find-skills/SKILL.md +141 -0
- package/framework/skills/find-skills/examples.md +35 -0
- package/framework/skills/gitlab-mcp/SKILL.md +83 -0
- package/framework/skills/gitlab-mcp/examples.md +31 -0
- package/framework/skills/gitlab-mcp/references/code-review.md +110 -0
- package/framework/skills/gitlab-mcp/references/issues.md +141 -0
- package/framework/skills/gitlab-mcp/references/merge-requests.md +120 -0
- package/framework/skills/gitlab-mcp/references/pipelines.md +67 -0
- package/framework/skills/gitlab-mcp/references/search.md +17 -0
- package/framework/skills/gitlab-mcp/references/webhooks.md +32 -0
- package/framework/skills/gitlab-mcp/references/work-items.md +50 -0
- package/framework/skills/jira-mcp/SKILL.md +57 -0
- package/framework/skills/jira-mcp/examples.md +31 -0
- package/framework/skills/jira-mcp/references/comments.md +27 -0
- package/framework/skills/jira-mcp/references/issues.md +97 -0
- package/framework/skills/jira-mcp/references/projects.md +39 -0
- package/framework/skills/laravel-best-practices/SKILL.md +229 -0
- package/framework/skills/laravel-best-practices/examples.md +31 -0
- package/framework/skills/laravel-best-practices/references/advanced-queries.md +106 -0
- package/framework/skills/laravel-best-practices/references/architecture.md +202 -0
- package/framework/skills/laravel-best-practices/references/blade-views.md +36 -0
- package/framework/skills/laravel-best-practices/references/caching.md +70 -0
- package/framework/skills/laravel-best-practices/references/collections.md +44 -0
- package/framework/skills/laravel-best-practices/references/config.md +73 -0
- package/framework/skills/laravel-best-practices/references/db-performance.md +192 -0
- package/framework/skills/laravel-best-practices/references/eloquent.md +148 -0
- package/framework/skills/laravel-best-practices/references/error-handling.md +72 -0
- package/framework/skills/laravel-best-practices/references/events-notifications.md +52 -0
- package/framework/skills/laravel-best-practices/references/http-client.md +160 -0
- package/framework/skills/laravel-best-practices/references/mail.md +27 -0
- package/framework/skills/laravel-best-practices/references/migrations.md +121 -0
- package/framework/skills/laravel-best-practices/references/passport.md +197 -0
- package/framework/skills/laravel-best-practices/references/pennant.md +61 -0
- package/framework/skills/laravel-best-practices/references/pest-testing.md +166 -0
- package/framework/skills/laravel-best-practices/references/pulse.md +196 -0
- package/framework/skills/laravel-best-practices/references/queue-jobs.md +144 -0
- package/framework/skills/laravel-best-practices/references/routing.md +99 -0
- package/framework/skills/laravel-best-practices/references/scheduling.md +39 -0
- package/framework/skills/laravel-best-practices/references/scout.md +176 -0
- package/framework/skills/laravel-best-practices/references/security.md +198 -0
- package/framework/skills/laravel-best-practices/references/spatie-laravel-backup.md +222 -0
- package/framework/skills/laravel-best-practices/references/spatie-laravel-permission.md +272 -0
- package/framework/skills/laravel-best-practices/references/spatie-medialibrary.md +672 -0
- package/framework/skills/laravel-best-practices/references/style.md +125 -0
- package/framework/skills/laravel-best-practices/references/tailwindcss.md +112 -0
- package/framework/skills/laravel-best-practices/references/testing.md +43 -0
- package/framework/skills/laravel-best-practices/references/validation.md +75 -0
- package/framework/skills/lavish/SKILL.md +67 -0
- package/framework/skills/lavish/examples.md +31 -0
- package/framework/skills/notion-mcp/SKILL.md +57 -0
- package/framework/skills/notion-mcp/examples.md +31 -0
- package/framework/skills/notion-mcp/references/comments.md +112 -0
- package/framework/skills/notion-mcp/references/databases.md +193 -0
- package/framework/skills/notion-mcp/references/pages.md +235 -0
- package/framework/skills/skill-creator/LICENSE.txt +202 -0
- package/framework/skills/skill-creator/SKILL.md +485 -0
- package/framework/skills/skill-creator/agents/analyzer.md +274 -0
- package/framework/skills/skill-creator/agents/comparator.md +202 -0
- package/framework/skills/skill-creator/agents/grader.md +223 -0
- package/framework/skills/skill-creator/assets/eval_review.html +146 -0
- package/framework/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/framework/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/framework/skills/skill-creator/examples.md +31 -0
- package/framework/skills/skill-creator/references/schemas.md +430 -0
- package/framework/skills/skill-creator/scripts/__init__.py +0 -0
- package/framework/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/framework/skills/skill-creator/scripts/generate_report.py +326 -0
- package/framework/skills/skill-creator/scripts/improve_description.py +247 -0
- package/framework/skills/skill-creator/scripts/package_skill.py +136 -0
- package/framework/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/framework/skills/skill-creator/scripts/run_eval.py +310 -0
- package/framework/skills/skill-creator/scripts/run_loop.py +328 -0
- package/framework/skills/skill-creator/scripts/utils.py +47 -0
- package/framework/styles/README.md +35 -0
- package/framework/styles/linear/DESIGN.md +478 -0
- package/framework/styles/linear/README.md +36 -0
- package/framework/styles/linear/assets/preview.jpg +0 -0
- package/framework/styles/raycast/DESIGN.md +495 -0
- package/framework/styles/raycast/README.md +35 -0
- package/framework/styles/raycast/assets/preview.jpg +0 -0
- package/package.json +33 -0
- package/src/agent-configs.js +96 -0
- package/src/catalog.js +145 -0
- package/src/cli.js +254 -0
- package/src/installer.js +303 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Eloquent Best Practices
|
|
2
|
+
|
|
3
|
+
## Use Correct Relationship Types
|
|
4
|
+
|
|
5
|
+
Use `hasMany`, `belongsTo`, `morphMany`, etc. with proper return type hints.
|
|
6
|
+
|
|
7
|
+
```php
|
|
8
|
+
public function comments(): HasMany
|
|
9
|
+
{
|
|
10
|
+
return $this->hasMany(Comment::class);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public function author(): BelongsTo
|
|
14
|
+
{
|
|
15
|
+
return $this->belongsTo(User::class, 'user_id');
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Use Local Scopes for Reusable Queries
|
|
20
|
+
|
|
21
|
+
Extract reusable query constraints into local scopes to avoid duplication.
|
|
22
|
+
|
|
23
|
+
Incorrect:
|
|
24
|
+
```php
|
|
25
|
+
$active = User::where('verified', true)->whereNotNull('activated_at')->get();
|
|
26
|
+
$articles = Article::whereHas('user', function ($q) {
|
|
27
|
+
$q->where('verified', true)->whereNotNull('activated_at');
|
|
28
|
+
})->get();
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Correct:
|
|
32
|
+
```php
|
|
33
|
+
public function scopeActive(Builder $query): Builder
|
|
34
|
+
{
|
|
35
|
+
return $query->where('verified', true)->whereNotNull('activated_at');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Usage
|
|
39
|
+
$active = User::active()->get();
|
|
40
|
+
$articles = Article::whereHas('user', fn ($q) => $q->active())->get();
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Apply Global Scopes Sparingly
|
|
44
|
+
|
|
45
|
+
Global scopes silently modify every query on the model, making debugging difficult. Prefer local scopes and reserve global scopes for truly universal constraints like soft deletes or multi-tenancy.
|
|
46
|
+
|
|
47
|
+
Incorrect (global scope for a conditional filter):
|
|
48
|
+
```php
|
|
49
|
+
class PublishedScope implements Scope
|
|
50
|
+
{
|
|
51
|
+
public function apply(Builder $builder, Model $model): void
|
|
52
|
+
{
|
|
53
|
+
$builder->where('published', true);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Now admin panels, reports, and background jobs all silently skip drafts
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Correct (local scope you opt into):
|
|
60
|
+
```php
|
|
61
|
+
public function scopePublished(Builder $query): Builder
|
|
62
|
+
{
|
|
63
|
+
return $query->where('published', true);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
Post::published()->paginate(); // Explicit
|
|
67
|
+
Post::paginate(); // Admin sees all
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Define Attribute Casts
|
|
71
|
+
|
|
72
|
+
Use the `casts()` method (or `$casts` property following project convention) for automatic type conversion.
|
|
73
|
+
|
|
74
|
+
```php
|
|
75
|
+
protected function casts(): array
|
|
76
|
+
{
|
|
77
|
+
return [
|
|
78
|
+
'is_active' => 'boolean',
|
|
79
|
+
'metadata' => 'array',
|
|
80
|
+
'total' => 'decimal:2',
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Cast Date Columns Properly
|
|
86
|
+
|
|
87
|
+
Always cast date columns. Use Carbon instances in templates instead of formatting strings manually.
|
|
88
|
+
|
|
89
|
+
Incorrect:
|
|
90
|
+
```blade
|
|
91
|
+
{{ Carbon::createFromFormat('Y-d-m H-i', $order->ordered_at)->toDateString() }}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Correct:
|
|
95
|
+
```php
|
|
96
|
+
protected function casts(): array
|
|
97
|
+
{
|
|
98
|
+
return [
|
|
99
|
+
'ordered_at' => 'datetime',
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```blade
|
|
105
|
+
{{ $order->ordered_at->toDateString() }}
|
|
106
|
+
{{ $order->ordered_at->format('m-d') }}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Use `whereBelongsTo()` for Relationship Queries
|
|
110
|
+
|
|
111
|
+
Cleaner than manually specifying foreign keys.
|
|
112
|
+
|
|
113
|
+
Incorrect:
|
|
114
|
+
```php
|
|
115
|
+
Post::where('user_id', $user->id)->get();
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Correct:
|
|
119
|
+
```php
|
|
120
|
+
Post::whereBelongsTo($user)->get();
|
|
121
|
+
Post::whereBelongsTo($user, 'author')->get();
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Avoid Hardcoded Table Names in Queries
|
|
125
|
+
|
|
126
|
+
Never use string literals for table names in raw queries, joins, or subqueries. Hardcoded table names make it impossible to find all places a model is used and break refactoring (e.g., renaming a table requires hunting through every raw string).
|
|
127
|
+
|
|
128
|
+
Incorrect:
|
|
129
|
+
```php
|
|
130
|
+
DB::table('users')->where('active', true)->get();
|
|
131
|
+
|
|
132
|
+
$query->join('companies', 'companies.id', '=', 'users.company_id');
|
|
133
|
+
|
|
134
|
+
DB::select('SELECT * FROM orders WHERE status = ?', ['pending']);
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Correct — reference the model's table:
|
|
138
|
+
```php
|
|
139
|
+
DB::table((new User)->getTable())->where('active', true)->get();
|
|
140
|
+
|
|
141
|
+
// Even better — use Eloquent or the query builder instead of raw SQL
|
|
142
|
+
User::where('active', true)->get();
|
|
143
|
+
Order::where('status', 'pending')->get();
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Prefer Eloquent queries and relationships over `DB::table()` whenever possible — they already reference the model's table. When `DB::table()` or raw joins are unavoidable, always use `(new Model)->getTable()` to keep the reference traceable.
|
|
147
|
+
|
|
148
|
+
**Exception — migrations:** In migrations, hardcoded table names via `DB::table('settings')` are acceptable and preferred. Models change over time but migrations are frozen snapshots — referencing a model that is later renamed or deleted would break the migration.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Error Handling Best Practices
|
|
2
|
+
|
|
3
|
+
## Exception Reporting and Rendering
|
|
4
|
+
|
|
5
|
+
There are two valid approaches — choose one and apply it consistently across the project.
|
|
6
|
+
|
|
7
|
+
**Co-location on the exception class** — keeps behavior alongside the exception definition, easier to find:
|
|
8
|
+
|
|
9
|
+
```php
|
|
10
|
+
class InvalidOrderException extends Exception
|
|
11
|
+
{
|
|
12
|
+
public function report(): void { /* custom reporting */ }
|
|
13
|
+
|
|
14
|
+
public function render(Request $request): Response
|
|
15
|
+
{
|
|
16
|
+
return response()->view('errors.invalid-order', status: 422);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Centralized in `bootstrap/app.php`** — all exception handling in one place, easier to see the full picture:
|
|
22
|
+
|
|
23
|
+
```php
|
|
24
|
+
->withExceptions(function (Exceptions $exceptions) {
|
|
25
|
+
$exceptions->report(function (InvalidOrderException $e) { /* ... */ });
|
|
26
|
+
$exceptions->render(function (InvalidOrderException $e, Request $request) {
|
|
27
|
+
return response()->view('errors.invalid-order', status: 422);
|
|
28
|
+
});
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Check the existing codebase and follow whichever pattern is already established.
|
|
33
|
+
|
|
34
|
+
## Use `ShouldntReport` for Exceptions That Should Never Log
|
|
35
|
+
|
|
36
|
+
More discoverable than listing classes in `dontReport()`.
|
|
37
|
+
|
|
38
|
+
```php
|
|
39
|
+
class PodcastProcessingException extends Exception implements ShouldntReport {}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Throttle High-Volume Exceptions
|
|
43
|
+
|
|
44
|
+
A single failing integration can flood error tracking. Use `throttle()` to rate-limit per exception type.
|
|
45
|
+
|
|
46
|
+
## Enable `dontReportDuplicates()`
|
|
47
|
+
|
|
48
|
+
Prevents the same exception instance from being logged multiple times when `report($e)` is called in multiple catch blocks.
|
|
49
|
+
|
|
50
|
+
## Force JSON Error Rendering for API Routes
|
|
51
|
+
|
|
52
|
+
Laravel auto-detects `Accept: application/json` but API clients may not set it. Explicitly declare JSON rendering for API routes.
|
|
53
|
+
|
|
54
|
+
```php
|
|
55
|
+
$exceptions->shouldRenderJsonWhen(function (Request $request, Throwable $e) {
|
|
56
|
+
return $request->is('api/*') || $request->expectsJson();
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Add Context to Exception Classes
|
|
61
|
+
|
|
62
|
+
Attach structured data to exceptions at the source via a `context()` method — Laravel includes it automatically in the log entry.
|
|
63
|
+
|
|
64
|
+
```php
|
|
65
|
+
class InvalidOrderException extends Exception
|
|
66
|
+
{
|
|
67
|
+
public function context(): array
|
|
68
|
+
{
|
|
69
|
+
return ['order_id' => $this->orderId];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Events & Notifications Best Practices
|
|
2
|
+
|
|
3
|
+
## Rely on Event Discovery
|
|
4
|
+
|
|
5
|
+
Laravel auto-discovers listeners by reading `handle(EventType $event)` type-hints. No manual registration needed in `AppServiceProvider`.
|
|
6
|
+
|
|
7
|
+
## Run `event:cache` in Production Deploy
|
|
8
|
+
|
|
9
|
+
Event discovery scans the filesystem per-request in dev. Cache it in production: `php artisan optimize` or `php artisan event:cache`.
|
|
10
|
+
|
|
11
|
+
## Use `ShouldDispatchAfterCommit` Inside Transactions
|
|
12
|
+
|
|
13
|
+
Without it, a queued listener may process before the DB transaction commits, reading data that doesn't exist yet.
|
|
14
|
+
|
|
15
|
+
```php
|
|
16
|
+
class OrderShipped implements ShouldDispatchAfterCommit {}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Always Queue Notifications
|
|
20
|
+
|
|
21
|
+
Notifications often hit external APIs (email, SMS, Slack). Without `ShouldQueue`, they block the HTTP response.
|
|
22
|
+
|
|
23
|
+
```php
|
|
24
|
+
class InvoicePaid extends Notification implements ShouldQueue
|
|
25
|
+
{
|
|
26
|
+
use Queueable;
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Use `afterCommit()` on Notifications in Transactions
|
|
31
|
+
|
|
32
|
+
Same race condition as events — call `afterCommit()` to delay dispatch until the transaction commits.
|
|
33
|
+
|
|
34
|
+
```php
|
|
35
|
+
$user->notify((new InvoicePaid($invoice))->afterCommit());
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Route Notification Channels to Dedicated Queues
|
|
39
|
+
|
|
40
|
+
Mail and database notifications have different priorities. Use `viaQueues()` to route them to separate queues.
|
|
41
|
+
|
|
42
|
+
## Use On-Demand Notifications for Non-User Recipients
|
|
43
|
+
|
|
44
|
+
Avoid creating dummy models to send notifications to arbitrary addresses.
|
|
45
|
+
|
|
46
|
+
```php
|
|
47
|
+
Notification::route('mail', 'admin@example.com')->notify(new SystemAlert());
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Implement `HasLocalePreference` on Notifiable Models
|
|
51
|
+
|
|
52
|
+
Laravel automatically uses the user's preferred locale for all notifications and mailables — no per-call `locale()` needed.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# HTTP Client Best Practices
|
|
2
|
+
|
|
3
|
+
## Always Set Explicit Timeouts
|
|
4
|
+
|
|
5
|
+
The default timeout is 30 seconds — too long for most API calls. Always set explicit `timeout` and `connectTimeout` to fail fast.
|
|
6
|
+
|
|
7
|
+
Incorrect:
|
|
8
|
+
```php
|
|
9
|
+
$response = Http::get('https://api.example.com/users');
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Correct:
|
|
13
|
+
```php
|
|
14
|
+
$response = Http::timeout(5)
|
|
15
|
+
->connectTimeout(3)
|
|
16
|
+
->get('https://api.example.com/users');
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
For service-specific clients, define timeouts in a macro:
|
|
20
|
+
|
|
21
|
+
```php
|
|
22
|
+
Http::macro('github', function () {
|
|
23
|
+
return Http::baseUrl('https://api.github.com')
|
|
24
|
+
->timeout(10)
|
|
25
|
+
->connectTimeout(3)
|
|
26
|
+
->withToken(config('services.github.token'));
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
$response = Http::github()->get('/repos/laravel/framework');
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Use Retry with Backoff for External APIs
|
|
33
|
+
|
|
34
|
+
External APIs have transient failures. Use `retry()` with increasing delays.
|
|
35
|
+
|
|
36
|
+
Incorrect:
|
|
37
|
+
```php
|
|
38
|
+
$response = Http::post('https://api.stripe.com/v1/charges', $data);
|
|
39
|
+
|
|
40
|
+
if ($response->failed()) {
|
|
41
|
+
throw new PaymentFailedException('Charge failed');
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Correct:
|
|
46
|
+
```php
|
|
47
|
+
$response = Http::retry([100, 500, 1000])
|
|
48
|
+
->timeout(10)
|
|
49
|
+
->post('https://api.stripe.com/v1/charges', $data);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Only retry on specific errors:
|
|
53
|
+
|
|
54
|
+
```php
|
|
55
|
+
$response = Http::retry(3, 100, function (Throwable $exception, PendingRequest $request) {
|
|
56
|
+
return $exception instanceof ConnectionException
|
|
57
|
+
|| ($exception instanceof RequestException && $exception->response->serverError());
|
|
58
|
+
})->post('https://api.example.com/data');
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Handle Errors Explicitly
|
|
62
|
+
|
|
63
|
+
The HTTP Client does not throw on 4xx/5xx by default. Always check status or use `throw()`.
|
|
64
|
+
|
|
65
|
+
Incorrect:
|
|
66
|
+
```php
|
|
67
|
+
$response = Http::get('https://api.example.com/users/1');
|
|
68
|
+
$user = $response->json(); // Could be an error body
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Correct:
|
|
72
|
+
```php
|
|
73
|
+
$response = Http::timeout(5)
|
|
74
|
+
->get('https://api.example.com/users/1')
|
|
75
|
+
->throw();
|
|
76
|
+
|
|
77
|
+
$user = $response->json();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
For graceful degradation:
|
|
81
|
+
|
|
82
|
+
```php
|
|
83
|
+
$response = Http::get('https://api.example.com/users/1');
|
|
84
|
+
|
|
85
|
+
if ($response->successful()) {
|
|
86
|
+
return $response->json();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if ($response->notFound()) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
$response->throw();
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Use Request Pooling for Concurrent Requests
|
|
97
|
+
|
|
98
|
+
When making multiple independent API calls, use `Http::pool()` instead of sequential calls.
|
|
99
|
+
|
|
100
|
+
Incorrect:
|
|
101
|
+
```php
|
|
102
|
+
$users = Http::get('https://api.example.com/users')->json();
|
|
103
|
+
$posts = Http::get('https://api.example.com/posts')->json();
|
|
104
|
+
$comments = Http::get('https://api.example.com/comments')->json();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Correct:
|
|
108
|
+
```php
|
|
109
|
+
use Illuminate\Http\Client\Pool;
|
|
110
|
+
|
|
111
|
+
$responses = Http::pool(fn (Pool $pool) => [
|
|
112
|
+
$pool->as('users')->get('https://api.example.com/users'),
|
|
113
|
+
$pool->as('posts')->get('https://api.example.com/posts'),
|
|
114
|
+
$pool->as('comments')->get('https://api.example.com/comments'),
|
|
115
|
+
]);
|
|
116
|
+
|
|
117
|
+
$users = $responses['users']->json();
|
|
118
|
+
$posts = $responses['posts']->json();
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Fake HTTP Calls in Tests
|
|
122
|
+
|
|
123
|
+
Never make real HTTP requests in tests. Use `Http::fake()` and `preventStrayRequests()`.
|
|
124
|
+
|
|
125
|
+
Incorrect:
|
|
126
|
+
```php
|
|
127
|
+
it('syncs user from API', function () {
|
|
128
|
+
$service = new UserSyncService;
|
|
129
|
+
$service->sync(1); // Hits the real API
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Correct:
|
|
134
|
+
```php
|
|
135
|
+
it('syncs user from API', function () {
|
|
136
|
+
Http::preventStrayRequests();
|
|
137
|
+
|
|
138
|
+
Http::fake([
|
|
139
|
+
'api.example.com/users/1' => Http::response([
|
|
140
|
+
'name' => 'John Doe',
|
|
141
|
+
'email' => 'john@example.com',
|
|
142
|
+
]),
|
|
143
|
+
]);
|
|
144
|
+
|
|
145
|
+
$service = new UserSyncService;
|
|
146
|
+
$service->sync(1);
|
|
147
|
+
|
|
148
|
+
Http::assertSent(function (Request $request) {
|
|
149
|
+
return $request->url() === 'https://api.example.com/users/1';
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Test failure scenarios too:
|
|
155
|
+
|
|
156
|
+
```php
|
|
157
|
+
Http::fake([
|
|
158
|
+
'api.example.com/*' => Http::failedConnection(),
|
|
159
|
+
]);
|
|
160
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Mail Best Practices
|
|
2
|
+
|
|
3
|
+
## Implement `ShouldQueue` on the Mailable Class
|
|
4
|
+
|
|
5
|
+
Makes queueing the default regardless of how the mailable is dispatched. No need to remember `Mail::queue()` at every call site — `Mail::send()` also queues it.
|
|
6
|
+
|
|
7
|
+
## Use `afterCommit()` on Mailables Inside Transactions
|
|
8
|
+
|
|
9
|
+
A queued mailable dispatched inside a transaction may process before the commit. Use `$this->afterCommit()` in the constructor.
|
|
10
|
+
|
|
11
|
+
## Use `assertQueued()` Not `assertSent()` for Queued Mailables
|
|
12
|
+
|
|
13
|
+
`Mail::assertSent()` only catches synchronous mail. Queued mailables fail `assertSent` with a "Did you mean to use assertQueued()?" hint.
|
|
14
|
+
|
|
15
|
+
Incorrect: `Mail::assertSent(OrderShipped::class);` when mailable implements `ShouldQueue`.
|
|
16
|
+
|
|
17
|
+
Correct: `Mail::assertQueued(OrderShipped::class);`
|
|
18
|
+
|
|
19
|
+
## Use Markdown Mailables for Transactional Emails
|
|
20
|
+
|
|
21
|
+
Markdown mailables auto-generate both HTML and plain-text versions, use responsive components, and allow global style customization. Generate with `--markdown` flag.
|
|
22
|
+
|
|
23
|
+
## Separate Content Tests from Sending Tests
|
|
24
|
+
|
|
25
|
+
Content tests: instantiate the mailable directly, call `assertSeeInHtml()`.
|
|
26
|
+
Sending tests: use `Mail::fake()` and `assertSent()`/`assertQueued()`.
|
|
27
|
+
Don't mix them — it conflates concerns and makes tests brittle.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Migration Best Practices
|
|
2
|
+
|
|
3
|
+
## Generate Migrations with Artisan
|
|
4
|
+
|
|
5
|
+
Always use `php artisan make:migration` for consistent naming and timestamps.
|
|
6
|
+
|
|
7
|
+
Incorrect (manually created file):
|
|
8
|
+
```php
|
|
9
|
+
// database/migrations/posts_migration.php ← wrong naming, no timestamp
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Correct (Artisan-generated):
|
|
13
|
+
```bash
|
|
14
|
+
php artisan make:migration create_posts_table
|
|
15
|
+
php artisan make:migration add_slug_to_posts_table
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Use `constrained()` for Foreign Keys
|
|
19
|
+
|
|
20
|
+
Automatic naming and referential integrity.
|
|
21
|
+
|
|
22
|
+
```php
|
|
23
|
+
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
|
|
24
|
+
|
|
25
|
+
// Non-standard names
|
|
26
|
+
$table->foreignId('author_id')->constrained('users');
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Never Modify Deployed Migrations
|
|
30
|
+
|
|
31
|
+
Once a migration has run in production, treat it as immutable. Create a new migration to change the table.
|
|
32
|
+
|
|
33
|
+
Incorrect (editing a deployed migration):
|
|
34
|
+
```php
|
|
35
|
+
// 2024_01_01_create_posts_table.php — already in production
|
|
36
|
+
$table->string('slug')->unique(); // ← added after deployment
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Correct (new migration to alter):
|
|
40
|
+
```php
|
|
41
|
+
// 2024_03_15_add_slug_to_posts_table.php
|
|
42
|
+
Schema::table('posts', function (Blueprint $table) {
|
|
43
|
+
$table->string('slug')->unique()->after('title');
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Add Indexes in the Migration
|
|
48
|
+
|
|
49
|
+
Add indexes when creating the table, not as an afterthought. Columns used in `WHERE`, `ORDER BY`, and `JOIN` clauses need indexes.
|
|
50
|
+
|
|
51
|
+
Incorrect:
|
|
52
|
+
```php
|
|
53
|
+
Schema::create('orders', function (Blueprint $table) {
|
|
54
|
+
$table->id();
|
|
55
|
+
$table->foreignId('user_id')->constrained();
|
|
56
|
+
$table->string('status');
|
|
57
|
+
$table->timestamps();
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Correct:
|
|
62
|
+
```php
|
|
63
|
+
Schema::create('orders', function (Blueprint $table) {
|
|
64
|
+
$table->id();
|
|
65
|
+
$table->foreignId('user_id')->constrained()->index();
|
|
66
|
+
$table->string('status')->index();
|
|
67
|
+
$table->timestamp('shipped_at')->nullable()->index();
|
|
68
|
+
$table->timestamps();
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Mirror Defaults in Model `$attributes`
|
|
73
|
+
|
|
74
|
+
When a column has a database default, mirror it in the model so new instances have correct values before saving.
|
|
75
|
+
|
|
76
|
+
```php
|
|
77
|
+
// Migration
|
|
78
|
+
$table->string('status')->default('pending');
|
|
79
|
+
|
|
80
|
+
// Model
|
|
81
|
+
protected $attributes = [
|
|
82
|
+
'status' => 'pending',
|
|
83
|
+
];
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Write Reversible `down()` Methods by Default
|
|
87
|
+
|
|
88
|
+
Implement `down()` for schema changes that can be safely reversed so `migrate:rollback` works in CI and failed deployments.
|
|
89
|
+
|
|
90
|
+
```php
|
|
91
|
+
public function down(): void
|
|
92
|
+
{
|
|
93
|
+
Schema::table('posts', function (Blueprint $table) {
|
|
94
|
+
$table->dropColumn('slug');
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
For intentionally irreversible migrations (e.g., destructive data backfills), leave a clear comment and require a forward fix migration instead of pretending rollback is supported.
|
|
100
|
+
|
|
101
|
+
## Keep Migrations Focused
|
|
102
|
+
|
|
103
|
+
One concern per migration. Never mix DDL (schema changes) and DML (data manipulation).
|
|
104
|
+
|
|
105
|
+
Incorrect (partial failure creates unrecoverable state):
|
|
106
|
+
```php
|
|
107
|
+
public function up(): void
|
|
108
|
+
{
|
|
109
|
+
Schema::create('settings', function (Blueprint $table) { ... });
|
|
110
|
+
DB::table('settings')->insert(['key' => 'version', 'value' => '1.0']);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Correct (separate migrations):
|
|
115
|
+
```php
|
|
116
|
+
// Migration 1: create_settings_table
|
|
117
|
+
Schema::create('settings', function (Blueprint $table) { ... });
|
|
118
|
+
|
|
119
|
+
// Migration 2: seed_default_settings
|
|
120
|
+
DB::table('settings')->insert(['key' => 'version', 'value' => '1.0']);
|
|
121
|
+
```
|