.github/skills/laravel-best-practices/SKILL.md
Apply this skill whenever writing, reviewing, or refactoring Laravel PHP code. This includes creating or modifying controllers, models, migrations, form requests, policies, jobs, scheduled commands, service classes, and Eloquent queries. Triggers for N+1 and query performance issues, caching strategies, authorization and security patterns, validation, error handling, queue and job configuration, route definitions, and architectural decisions. Also use for Laravel code reviews and refactoring existing Laravel code to follow best practices. Covers any task involving Laravel backend PHP code patterns.
npx skillsauth add Dregozone/Dregozone laravel-best-practicesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Best practices for Laravel, prioritized by impact. Each rule teaches what to do and why. For exact API syntax, verify with search-docs.
Before applying any rule, check what the application already does. Laravel offers multiple valid approaches — the best choice is the one the codebase already uses, even if another pattern would be theoretically better. Inconsistency is worse than a suboptimal pattern.
Check sibling files, related controllers, models, or tests for established patterns. If one exists, follow it — don't introduce a second way. These rules are defaults for when no pattern exists yet, not overrides.
rules/db-performance.mdwith() to prevent N+1 queriesModel::preventLazyLoading() in developmentSELECT *chunk() / chunkById() for large datasetsWHERE, ORDER BY, JOINwithCount() instead of loading relations to countcursor() for memory-efficient read-only iterationrules/advanced-queries.mdaddSelect() subqueries over eager-loading entire has-many for a single valuebelongsToCASE WHEN in selectRaw) over multiple count queriessetRelation() to prevent circular N+1 querieswhereIn + pluck() over whereHas for better index usageorderBy column orderorderBy for has-many sorting (avoid joins)rules/security.md$fillable or $guarded on every model, authorize every action via policies or gates{{ }} for output escaping, @csrf on all POST/PUT/DELETE forms, throttle on auth and API routes.env, use config() for secrets, encrypted cast for sensitive DB fieldsrules/caching.mdCache::remember() over manual get/putCache::flexible() for stale-while-revalidate on high-traffic dataCache::memo() to avoid redundant cache hits within a requestCache::add() for atomic conditional writesonce() to memoize per-request or per-object lifetimeCache::lock() / lockForUpdate() for race conditionsrules/eloquent.mdcasts() methodwhereBelongsTo($model) for cleaner queries(new Model)->getTable() or Eloquent queriesrules/validation.md['required', 'email'] for new code; follow existing convention$request->validated() only — never $request->all()Rule::when() for conditional validationafter() instead of withValidator()rules/config.mdenv() only inside config filesApp::environment() or app()->isProduction()rules/testing.mdLazilyRefreshDatabase over RefreshDatabase for speedassertModelExists() over raw assertDatabaseHas()Event::fake(), Exceptions::fake(), etc.) — but always after factory setup, not beforerecycle() to share relationship instances across factoriesrules/queue-jobs.mdretry_after must exceed job timeout; use exponential backoff [1, 5, 10]ShouldBeUnique to prevent duplicates; ShouldBeUniqueUntilProcessing for early lock releasefailed(); with retryUntil(), set $tries = 0RateLimited middleware for external API calls; Bus::batch() for related jobsrules/routing.mdRoute::resource() or apiResource()rules/http-client.mdtimeout and connectTimeout on every requestretry() with exponential backoff for external APIsthrow()Http::pool() for concurrent independent requestsHttp::fake() and preventStrayRequests() in testsrules/events-notifications.md, rules/mail.mdevent:cache in productionShouldDispatchAfterCommit / afterCommit() inside transactionsShouldQueueHasLocalePreference on notifiable modelsassertQueued() not assertSent() for queued mailablesrules/error-handling.mdreport()/render() on exception classes or in bootstrap/app.php — follow existing patternShouldntReport for exceptions that should never logdontReportDuplicates() for multi-catch scenarioscontext() on exception classesrules/scheduling.mdwithoutOverlapping() on variable-duration tasksonOneServer() on multi-server deploymentsrunInBackground() for concurrent long tasksenvironments() to restrict to appropriate environmentstakeUntilTimeout() for time-bounded processingrules/architecture.mdapp() helperORDER BY id DESC or created_at DESC; mb_* for UTF-8 safetydefer() for post-response work; Context for request-scoped data; Concurrency::run() for parallel executionrules/migrations.mdphp artisan make:migrationconstrained() for foreign keys$attributesdown() by default; forward-fix migrations for intentionally irreversible changesrules/collections.mdcursor() vs. lazy() — choose based on relationship needslazyById() when updating records while iteratingtoQuery() for bulk operations on collectionsrules/blade-views.md$attributes->merge() in component templates@include; @pushOnce for per-component scripts@aware for deeply nested component propsrules/style.mdStr, Arr, Number, Uri, Str::of(), $request->string()) over raw PHP functionsAlways use a sub-agent to read rule files and explore this skill's content.
search-docs for the installed Laravel versiontools
Always invoke when the user's message includes 'tailwind' in any form. Also invoke for: building responsive grid layouts (multi-column card grids, product grids), flex/grid page structures (dashboards with sidebars, fixed topbars, mobile-toggle navs), styling UI components (cards, tables, navbars, pricing sections, forms, inputs, badges), adding dark mode variants, fixing spacing or typography, and Tailwind v3/v4 work. The core use case: writing or fixing Tailwind utility classes in HTML templates (Blade, JSX, Vue). Skip for backend PHP logic, database queries, API routes, JavaScript with no HTML/CSS component, CSS file audits, build tool configuration, and vanilla CSS.
development
Use this skill for Pest PHP testing in Laravel projects only. Trigger whenever any test is being written, edited, fixed, or refactored — including fixing tests that broke after a code change, adding assertions, converting PHPUnit to Pest, adding datasets, and TDD workflows. Always activate when the user asks how to write something in Pest, mentions test files or directories (tests/Feature, tests/Unit) or architecture tests. Covers: test()/it()/expect() syntax, datasets, mocking, browser testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 3 features. Do not use for editing factories, seeders, migrations, controllers, models, or non-test PHP code.
tools
Use this skill for Flux UI development in Livewire applications only. Trigger when working with <flux:*> components, building or customizing Livewire component UIs, creating forms, modals, tables, or other interactive elements. Covers: flux: components (buttons, inputs, modals, forms, tables, date-pickers, kanban, badges, tooltips, etc.), component composition, Tailwind CSS styling, Heroicons/Lucide icon integration, validation patterns, responsive design, and theming. Do not use for non-Livewire frameworks or non-component styling.
testing
Configures Laravel Nightwatch data collection, sampling rates, filtering rules, and redaction policies. Use when setting up Nightwatch, managing data volume, protecting sensitive data (PII), or optimizing event collection for production workloads.