Refactor code structure for improved readability and maintainability
This commit is contained in:
21 files changed
+778
-694
No files matched your search
@@ -94,7 +94,7 @@ Check sibling files, related controllers, models, or tests for established patte
|
||||
### 9. Queue & Job Patterns → `rules/queue-jobs.md`
|
||||
|
||||
- `retry_after` must exceed job `timeout`; use exponential backoff `[1, 5, 10]`
|
||||
- `ShouldBeUnique` to prevent duplicates; `WithoutOverlapping::untilProcessing()` for concurrency
|
||||
- `ShouldBeUnique` to prevent duplicates; `ShouldBeUniqueUntilProcessing` for early lock release
|
||||
- Always implement `failed()`; with `retryUntil()`, set `$tries = 0`
|
||||
- `RateLimited` middleware for external API calls; `Bus::batch()` for related jobs
|
||||
- Horizon for complex multi-queue scenarios
|
||||
|
||||
@@ -82,7 +82,7 @@ $this->app->bind(PaymentGateway::class, StripeGateway::class);
|
||||
|
||||
## Default Sort by Descending
|
||||
|
||||
When no explicit order is specified, sort by `id` or `created_at` descending. Explicit ordering prevents cross-database inconsistencies between MySQL and Postgres.
|
||||
When no explicit order is specified, sort by `id` or `created_at` descending. Without an explicit `ORDER BY`, row order is undefined.
|
||||
|
||||
Incorrect:
|
||||
```php
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Use `Cache::remember()` Instead of Manual Get/Put
|
||||
|
||||
Atomic pattern prevents race conditions and removes boilerplate.
|
||||
Cleaner cache-aside pattern that removes boilerplate. use `Cache::lock()` for race conditions.
|
||||
|
||||
Incorrect:
|
||||
```php
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## `env()` Only in Config Files
|
||||
|
||||
Direct `env()` calls return `null` when config is cached.
|
||||
Direct `env()` calls may return `null` when config is cached.
|
||||
|
||||
Incorrect:
|
||||
```php
|
||||
|
||||
@@ -29,7 +29,11 @@ class InvoicePaid extends Notification implements ShouldQueue
|
||||
|
||||
## Use `afterCommit()` on Notifications in Transactions
|
||||
|
||||
Same race condition as events — the queued notification job may run before the transaction commits.
|
||||
Same race condition as events — call `afterCommit()` to delay dispatch until the transaction commits.
|
||||
|
||||
```php
|
||||
$user->notify((new InvoicePaid($invoice))->afterCommit());
|
||||
```
|
||||
|
||||
## Route Notification Channels to Dedicated Queues
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ $response = Http::retry([100, 500, 1000])
|
||||
Only retry on specific errors:
|
||||
|
||||
```php
|
||||
$response = Http::retry(3, 100, function (Exception $exception, PendingRequest $request) {
|
||||
$response = Http::retry(3, 100, function (Throwable $exception, PendingRequest $request) {
|
||||
return $exception instanceof ConnectionException
|
||||
|| ($exception instanceof RequestException && $exception->response->serverError());
|
||||
})->post('https://api.example.com/data');
|
||||
|
||||
@@ -10,7 +10,7 @@ A queued mailable dispatched inside a transaction may process before the commit.
|
||||
|
||||
## Use `assertQueued()` Not `assertSent()` for Queued Mailables
|
||||
|
||||
`Mail::assertSent()` only catches synchronous mail. Queued mailables silently pass `assertSent`, giving false confidence.
|
||||
`Mail::assertSent()` only catches synchronous mail. Queued mailables fail `assertSent` with a "Did you mean to use assertQueued()?" hint.
|
||||
|
||||
Incorrect: `Mail::assertSent(OrderShipped::class);` when mailable implements `ShouldQueue`.
|
||||
|
||||
|
||||
@@ -106,25 +106,23 @@ When using time-based retry limits, set `$tries = 0` to avoid premature failure.
|
||||
```php
|
||||
public $tries = 0;
|
||||
|
||||
public function retryUntil(): DateTime
|
||||
public function retryUntil(): \DateTimeInterface
|
||||
{
|
||||
return now()->addHours(4);
|
||||
}
|
||||
```
|
||||
|
||||
## Use `WithoutOverlapping::untilProcessing()`
|
||||
## Use `ShouldBeUniqueUntilProcessing` for Early Lock Release
|
||||
|
||||
Prevents concurrent execution while allowing new instances to queue.
|
||||
`ShouldBeUnique` holds the lock until the job completes. `ShouldBeUniqueUntilProcessing` releases it when processing starts, allowing new instances to queue.
|
||||
|
||||
```php
|
||||
public function middleware(): array
|
||||
class UpdateSearchIndex implements ShouldQueue, ShouldBeUniqueUntilProcessing
|
||||
{
|
||||
return [new WithoutOverlapping($this->product->id)->untilProcessing()];
|
||||
// Lock releases when processing begins, not when it finishes
|
||||
}
|
||||
```
|
||||
|
||||
Without `untilProcessing()`, the lock extends through queue wait time. With it, the lock releases when processing starts.
|
||||
|
||||
## Use Horizon for Complex Queue Scenarios
|
||||
|
||||
Use Laravel Horizon when you need monitoring, auto-scaling, failure tracking, or multiple queues with different priorities.
|
||||
|
||||
@@ -36,7 +36,8 @@ Use `Route::resource()` or `apiResource()` for RESTful endpoints.
|
||||
|
||||
```php
|
||||
Route::resource('posts', PostController::class);
|
||||
Route::apiResource('api/posts', Api\PostController::class);
|
||||
// In routes/api.php — the /api prefix is applied automatically
|
||||
Route::apiResource('posts', Api\PostController::class);
|
||||
```
|
||||
|
||||
## Keep Controllers Thin
|
||||
|
||||
@@ -32,7 +32,7 @@ Use policies or gates in controllers. Never skip authorization.
|
||||
|
||||
Incorrect:
|
||||
```php
|
||||
public function update(Request $request, Post $post)
|
||||
public function update(UpdatePostRequest $request, Post $post)
|
||||
{
|
||||
$post->update($request->validated());
|
||||
}
|
||||
@@ -90,7 +90,7 @@ Correct:
|
||||
|
||||
## CSRF Protection
|
||||
|
||||
Include `@csrf` in all POST/PUT/DELETE Blade forms. Not needed in Inertia.
|
||||
Include `@csrf` in all POST/PUT/DELETE Blade forms. In Inertia apps, the `@csrf` directive is automatically applied.
|
||||
|
||||
Incorrect:
|
||||
```blade
|
||||
@@ -121,7 +121,7 @@ Route::post('/login', LoginController::class)->middleware('throttle:login');
|
||||
|
||||
## Validate File Uploads
|
||||
|
||||
Validate MIME type, extension, and size. Never trust client-provided filenames.
|
||||
Validate extension, MIME type, and size. The `mimes` rule checks extensions; use `mimetypes` for actual MIME type validation. Never trust client-provided filenames.
|
||||
|
||||
```php
|
||||
public function rules(): array
|
||||
|
||||
Binary file not shown.
@@ -2,7 +2,7 @@
|
||||
|
||||
## Use `LazilyRefreshDatabase` Over `RefreshDatabase`
|
||||
|
||||
`RefreshDatabase` runs all migrations every test run even when the schema hasn't changed. `LazilyRefreshDatabase` only migrates when needed, significantly speeding up large suites.
|
||||
`RefreshDatabase` migrates once per process and wraps each test in a rolled-back transaction. `LazilyRefreshDatabase` skips even that first migration if the schema is already up to date.
|
||||
|
||||
## Use Model Assertions Over Raw Database Assertions
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ search-docs(['mcp tools', 'mcp resources', 'mcp validation'])
|
||||
|
||||
### Artisan Commands
|
||||
|
||||
Create MCP Primitives"
|
||||
Create MCP Primitives
|
||||
```bash
|
||||
php artisan make:mcp-tool ToolName
|
||||
php artisan make:mcp-resource ResourceName
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: pest-testing
|
||||
description: "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, tests/Browser), or needs browser testing, smoke testing multiple pages for JS errors, or architecture tests. Covers: it()/expect() syntax, datasets, mocking, browser testing (visit/click/fill), smoke testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 4 features. Do not use for factories, seeders, migrations, controllers, models, or non-test PHP code."
|
||||
description: "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, tests/Browser), or needs browser testing, smoke testing multiple pages for JS errors, or architecture tests. Covers: test()/it()/expect() syntax, datasets, mocking, browser testing (visit/click/fill), smoke testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 4 features. Do not use for factories, seeders, migrations, controllers, models, or non-test PHP code."
|
||||
license: MIT
|
||||
metadata:
|
||||
author: laravel
|
||||
@@ -18,6 +18,12 @@ Use `search-docs` for detailed Pest 4 patterns and documentation.
|
||||
|
||||
All tests must be written using Pest. Use `php artisan make:test --pest {name}`.
|
||||
|
||||
The `{name}` argument should include only the path and test name, but should not include the test suite.
|
||||
- Incorrect: `php artisan make:test --pest Feature/SomeFeatureTest` will generate `tests/Feature/Feature/SomeFeatureTest.php`
|
||||
- Correct: `php artisan make:test --pest SomeControllerTest` will generate `tests/Feature/SomeControllerTest.php`
|
||||
- Incorrect: `php artisan make:test --pest --unit Unit/SomeServiceTest` will generate `tests/Unit/Unit/SomeServiceTest.php`
|
||||
- Correct: `php artisan make:test --pest --unit SomeServiceTest` will generate `tests/Unit/SomeServiceTest.php`
|
||||
|
||||
### Test Organization
|
||||
|
||||
- Unit/Feature tests: `tests/Feature` and `tests/Unit` directories.
|
||||
@@ -26,6 +32,8 @@ All tests must be written using Pest. Use `php artisan make:test --pest {name}`.
|
||||
|
||||
### Basic Test Structure
|
||||
|
||||
Pest supports both `test()` and `it()` functions. Before writing new tests, check existing test files in the same directory to match the project's convention. Use `test()` if existing tests use `test()`, or `it()` if they use `it()`.
|
||||
|
||||
<!-- Basic Pest Test Example -->
|
||||
```php
|
||||
it('is true', function () {
|
||||
@@ -155,3 +163,4 @@ arch('controllers')
|
||||
- Forgetting datasets for repetitive validation tests
|
||||
- Deleting tests without approval
|
||||
- Forgetting `assertNoJavaScriptErrors()` in browser tests
|
||||
- Prefixing `Feature/` or `Unit/` in `{name}` when using `make:test`
|
||||
@@ -23,12 +23,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
|
||||
|
||||
## Skills Activation
|
||||
|
||||
This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck.
|
||||
|
||||
- `laravel-best-practices` — 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.
|
||||
- `mcp-development` — Use this skill for Laravel MCP development only. Trigger when creating or editing MCP tools, resources, prompts, or servers in Laravel projects. Covers: artisan make:mcp-* generators, mcp:inspector, routes/ai.php, Tool/Resource/Prompt classes, schema validation, shouldRegister(), OAuth setup, URI templates, read-only attributes, and MCP debugging. Do not use for non-Laravel MCP projects or generic AI features without MCP.
|
||||
- `pest-testing` — 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, tests/Browser), or needs browser testing, smoke testing multiple pages for JS errors, or architecture tests. Covers: it()/expect() syntax, datasets, mocking, browser testing (visit/click/fill), smoke testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 4 features. Do not use for factories, seeders, migrations, controllers, models, or non-test PHP code.
|
||||
- `tailwindcss-development` — 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.
|
||||
This project has domain-specific skills available in `**/skills/**`. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck.
|
||||
|
||||
## Conventions
|
||||
|
||||
@@ -107,6 +102,12 @@ This project has domain-specific skills available. You MUST activate the relevan
|
||||
- Prefer PHPDoc blocks over inline comments. Only add inline comments for exceptionally complex logic.
|
||||
- Use array shape type definitions in PHPDoc blocks.
|
||||
|
||||
=== deployments rules ===
|
||||
|
||||
# Deployment
|
||||
|
||||
- Laravel can be deployed using [Laravel Cloud](https://cloud.laravel.com/), which is the fastest way to deploy and scale production Laravel applications.
|
||||
|
||||
=== tests rules ===
|
||||
|
||||
# Test Enforcement
|
||||
@@ -181,6 +182,7 @@ This project has domain-specific skills available. You MUST activate the relevan
|
||||
## Pest
|
||||
|
||||
- This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`.
|
||||
- The `{name}` argument should not include the test suite directory. Use `php artisan make:test --pest SomeFeatureTest` instead of `php artisan make:test --pest Feature/SomeFeatureTest`.
|
||||
- Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`.
|
||||
- Do NOT delete tests without approval.
|
||||
|
||||
|
||||
@@ -23,12 +23,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
|
||||
|
||||
## Skills Activation
|
||||
|
||||
This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck.
|
||||
|
||||
- `laravel-best-practices` — 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.
|
||||
- `mcp-development` — Use this skill for Laravel MCP development only. Trigger when creating or editing MCP tools, resources, prompts, or servers in Laravel projects. Covers: artisan make:mcp-* generators, mcp:inspector, routes/ai.php, Tool/Resource/Prompt classes, schema validation, shouldRegister(), OAuth setup, URI templates, read-only attributes, and MCP debugging. Do not use for non-Laravel MCP projects or generic AI features without MCP.
|
||||
- `pest-testing` — 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, tests/Browser), or needs browser testing, smoke testing multiple pages for JS errors, or architecture tests. Covers: it()/expect() syntax, datasets, mocking, browser testing (visit/click/fill), smoke testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 4 features. Do not use for factories, seeders, migrations, controllers, models, or non-test PHP code.
|
||||
- `tailwindcss-development` — 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.
|
||||
This project has domain-specific skills available in `**/skills/**`. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck.
|
||||
|
||||
## Conventions
|
||||
|
||||
@@ -107,6 +102,12 @@ This project has domain-specific skills available. You MUST activate the relevan
|
||||
- Prefer PHPDoc blocks over inline comments. Only add inline comments for exceptionally complex logic.
|
||||
- Use array shape type definitions in PHPDoc blocks.
|
||||
|
||||
=== deployments rules ===
|
||||
|
||||
# Deployment
|
||||
|
||||
- Laravel can be deployed using [Laravel Cloud](https://cloud.laravel.com/), which is the fastest way to deploy and scale production Laravel applications.
|
||||
|
||||
=== tests rules ===
|
||||
|
||||
# Test Enforcement
|
||||
@@ -181,6 +182,7 @@ This project has domain-specific skills available. You MUST activate the relevan
|
||||
## Pest
|
||||
|
||||
- This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`.
|
||||
- The `{name}` argument should not include the test suite directory. Use `php artisan make:test --pest SomeFeatureTest` instead of `php artisan make:test --pest Feature/SomeFeatureTest`.
|
||||
- Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`.
|
||||
- Do NOT delete tests without approval.
|
||||
|
||||
|
||||
+5
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
/**
|
||||
* A helper file for Laravel, to provide autocomplete information to your IDE
|
||||
* Generated for Laravel 12.56.0.
|
||||
* Generated for Laravel 12.58.0.
|
||||
*
|
||||
* This file should not be included in your code, only analyzed by your IDE!
|
||||
*
|
||||
@@ -20592,6 +20592,7 @@ namespace Illuminate\Support\Facades {
|
||||
* @param array $headers
|
||||
* @param string|null $disposition
|
||||
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
* @throws UnableToRetrieveMetadata
|
||||
* @static
|
||||
*/
|
||||
public static function response($path, $name = null, $headers = [], $disposition = 'inline')
|
||||
@@ -20609,6 +20610,7 @@ namespace Illuminate\Support\Facades {
|
||||
* @param string|null $name
|
||||
* @param array $headers
|
||||
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
* @throws UnableToRetrieveMetadata
|
||||
* @static
|
||||
*/
|
||||
public static function serve($request, $path, $name = null, $headers = [])
|
||||
@@ -20625,6 +20627,7 @@ namespace Illuminate\Support\Facades {
|
||||
* @param string|null $name
|
||||
* @param array $headers
|
||||
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
* @throws UnableToRetrieveMetadata
|
||||
* @static
|
||||
*/
|
||||
public static function download($path, $name = null, $headers = [])
|
||||
@@ -20823,6 +20826,7 @@ namespace Illuminate\Support\Facades {
|
||||
*
|
||||
* @param string $path
|
||||
* @return string|false
|
||||
* @throws UnableToRetrieveMetadata
|
||||
* @static
|
||||
*/
|
||||
public static function mimeType($path)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"claude_code",
|
||||
"gemini"
|
||||
],
|
||||
"cloud": false,
|
||||
"guidelines": true,
|
||||
"herd_mcp": false,
|
||||
"mcp": true,
|
||||
|
||||
Generated
+408
-348
File diff suppressed because it is too large.
Load diff
Generated
+312
-312
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user