Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Add Docs
Essentials
https://github.com/nunomaduro/essentials
Admin
Essentials provides better defaults for Laravel applications, including strict models, auto-eager
...
Tokens:
6,617
Snippets:
61
Trust Score:
10
Update:
4 months ago
Context
Skills
Chat
Benchmark
75.9
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Laravel Essentials Laravel Essentials is a PHP package that provides better defaults for Laravel applications. It enhances Laravel projects by enabling strict model behavior, automatic eager loading of relationships, immutable dates, and other security and performance improvements. The package is designed for Laravel 11+ and PHP 8.3+, offering a curated set of opinionated configurations that help developers avoid common pitfalls and follow best practices. This package modifies Laravel's default behavior through a configurable system of "Configurables" - classes that automatically apply settings when the service provider boots. Each feature can be individually enabled or disabled through the `config/essentials.php` configuration file, allowing developers to adopt only the defaults they need. The package also includes Artisan commands for generating action classes and publishing opinionated code quality configurations for Pint and Rector. ## Installation Installing the package via Composer ```bash composer require nunomaduro/essentials ``` ## Publishing Configuration Publishing the configuration file to customize settings ```bash php artisan vendor:publish --tag=essentials-config ``` ```php // config/essentials.php return [ NunoMaduro\Essentials\Configurables\ShouldBeStrict::class => true, NunoMaduro\Essentials\Configurables\AutomaticallyEagerLoadRelationships::class => true, NunoMaduro\Essentials\Configurables\ImmutableDates::class => true, NunoMaduro\Essentials\Configurables\ForceScheme::class => true, NunoMaduro\Essentials\Configurables\Unguard::class => false, 'environments' => [ NunoMaduro\Essentials\Configurables\ForceScheme::class => ['production'], ], ]; ``` ## Strict Model Configuration Enforcing strict mode on Eloquent models to prevent common bugs ```php // Automatically enabled by Essentials // config/essentials.php NunoMaduro\Essentials\Configurables\ShouldBeStrict::class => true, // Before: accessing missing attributes silently returns null $user = User::find(1); $invalid = $user->non_existent_attribute; // null (no error) // After: accessing missing attributes throws an exception $user = User::find(1); $invalid = $user->non_existent_attribute; // LogicException thrown // Before: lazy loading relationships causes N+1 queries $users = User::all(); foreach ($users as $user) { echo $user->posts->count(); // N+1 queries } // After: lazy loading is prevented $users = User::all(); foreach ($users as $user) { echo $user->posts->count(); // LazyLoadingViolationException thrown } // Proper usage with eager loading $users = User::with('posts')->get(); foreach ($users as $user) { echo $user->posts->count(); // Single query } ``` ## Automatic Eager Loading Automatically eager loading relationships defined in model's $with property ```php // Automatically enabled by Essentials // config/essentials.php NunoMaduro\Essentials\Configurables\AutomaticallyEagerLoadRelationships::class => true, // Define relationships to eager load in your model namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class User extends Model { protected $with = ['posts', 'profile']; public function posts(): HasMany { return $this->hasMany(Post::class); } public function profile() { return $this->hasOne(Profile::class); } } // Usage: relationships are automatically loaded $users = User::all(); // Automatically includes posts and profile foreach ($users as $user) { echo $user->posts->count(); // No additional queries echo $user->profile->bio; // No additional queries } ``` ## Immutable Dates Configuration Using CarbonImmutable for all date operations to prevent mutations ```php // Automatically enabled by Essentials // config/essentials.php NunoMaduro\Essentials\Configurables\ImmutableDates::class => true, // Before: mutable dates can cause unexpected behavior $order = Order::find(1); $originalDate = $order->created_at; $newDate = $originalDate->addDays(7); // $originalDate is now modified - unexpected mutation // After: dates are immutable $order = Order::find(1); $originalDate = $order->created_at; // CarbonImmutable instance $newDate = $originalDate->addDays(7); // $originalDate remains unchanged, $newDate is a new instance echo $originalDate->toDateString(); // 2025-01-01 echo $newDate->toDateString(); // 2025-01-08 // Chain operations safely $date = now(); $tomorrow = $date->addDay(); $nextWeek = $date->addWeek(); // $date is never modified ``` ## Force HTTPS Scheme Forcing all generated URLs to use HTTPS ```php // Enabled by default in production environment // config/essentials.php NunoMaduro\Essentials\Configurables\ForceScheme::class => true, 'environments' => [ NunoMaduro\Essentials\Configurables\ForceScheme::class => ['production'], ], // All URLs generated by Laravel will use HTTPS route('user.profile', ['id' => 1]); // https://example.com/users/1 (not http://) url('/dashboard'); // https://example.com/dashboard asset('css/app.css'); // https://example.com/css/app.css // Useful in views <a href="{{ route('home') }}">Home</a> <!-- Generates: <a href="https://example.com">Home</a> --> ``` ## Prohibit Destructive Commands Blocking potentially destructive commands in production ```php // Automatically enabled by Essentials // config/essentials.php NunoMaduro\Essentials\Configurables\ProhibitDestructiveCommands::class => true, // In production environment php artisan migrate:fresh // RuntimeException: Destructive database commands are prohibited in production php artisan db:wipe // RuntimeException: Destructive database commands are prohibited in production // In local environment - commands work normally php artisan migrate:fresh // Migrations are dropped and re-run successfully // The protection is automatic based on app()->isProduction() ``` ## Set Default Password Validation Configuring default password validation rules ```php // Automatically enabled by Essentials // config/essentials.php NunoMaduro\Essentials\Configurables\SetDefaultPassword::class => true, // In production: strict password rules apply use Illuminate\Validation\Rules\Password; $request->validate([ 'password' => ['required', Password::defaults()], ]); // In production: min 12 chars, max 255 chars, not compromised // In local: no restrictions (null) // Custom validation in your request public function rules(): array { return [ 'email' => 'required|email', 'password' => ['required', Password::defaults()], 'password_confirmation' => 'required|same:password', ]; } // The password must be: // - At least 12 characters long (production only) // - Maximum 255 characters // - Not compromised in data breaches (production only) ``` ## Prevent Stray HTTP Requests Preventing unfaked HTTP requests during tests ```php // Automatically enabled during tests // config/essentials.php NunoMaduro\Essentials\Configurables\PreventStrayRequests::class => true, // In your test file use Illuminate\Support\Facades\Http; test('makes external API call', function () { // Without faking, this would throw RuntimeException // Http::get('https://api.example.com/users'); // Error! // Proper usage: fake the request first Http::fake([ 'api.example.com/*' => Http::response(['users' => []], 200), ]); $response = Http::get('https://api.example.com/users'); expect($response->json())->toHaveKey('users'); }); // Ensures all HTTP interactions are explicitly mocked // Prevents accidental real API calls during testing ``` ## Fake Sleep During Tests Faking sleep operations during tests to speed up execution ```php // Automatically enabled during tests // config/essentials.php NunoMaduro\Essentials\Configurables\FakeSleep::class => true, // In your application code use Illuminate\Support\Sleep; public function processWithRetry() { Sleep::for(5)->seconds(); // Would normally wait 5 seconds // Process something } // In your test - sleep is faked automatically test('processes with retry', function () { // This test runs instantly, no actual 5-second wait $result = app(Service::class)->processWithRetry(); expect($result)->toBeTrue(); }); // Assert sleep was called test('verifies sleep duration', function () { Sleep::fake(); app(Service::class)->processWithRetry(); Sleep::assertSlept(fn ($sleep) => $sleep->duration === 5); }); ``` ## Aggressive Asset Prefetching Configuring Vite to aggressively preload assets ```php // Automatically enabled by Essentials // config/essentials.php NunoMaduro\Essentials\Configurables\AggressivePrefetching::class => true, // In your Blade templates <!DOCTYPE html> <html> <head> @vite(['resources/css/app.css', 'resources/js/app.js']) </head> <body> <!-- Assets are aggressively prefetched for better performance --> <div id="app"> <!-- Your content --> </div> </body> </html> // The Vite helper automatically adds prefetch hints // Improves page load times by preloading JavaScript modules // Browser downloads dependencies before they're needed ``` ## Unguard Models (Optional) Disabling mass assignment protection globally ```php // Disabled by default - opt-in feature // config/essentials.php NunoMaduro\Essentials\Configurables\Unguard::class => false, // When enabled (use cautiously in trusted environments): NunoMaduro\Essentials\Configurables\Unguard::class => true, // Before: need to define $fillable or $guarded class User extends Model { protected $fillable = ['name', 'email', 'password']; } User::create($request->all()); // Only fillable attributes saved // After unguard is enabled: no $fillable needed class User extends Model { // No $fillable or $guarded property needed } User::create($request->all()); // All attributes can be mass assigned // WARNING: Only use in local/trusted environments // Can be a security risk in production ``` ## Make Action Command Generating action classes for business logic ```bash php artisan make:action CreateUserAction ``` ```php // Generated file: app/Actions/CreateUserAction.php <?php declare(strict_types=1); namespace App\Actions; use Illuminate\Support\Facades\DB; final readonly class CreateUserAction { /** * Execute the action. */ public function handle(): void { DB::transaction(function (): void { // }); } } // Usage in your controller use App\Actions\CreateUserAction; class UserController extends Controller { public function store(Request $request, CreateUserAction $action) { $validated = $request->validate([ 'name' => 'required|string', 'email' => 'required|email|unique:users', ]); $action->handle(); return redirect()->route('users.index'); } } ``` ## Essentials Pint Command Publishing opinionated Pint (code style) configuration ```bash php artisan essentials:pint --force --backup ``` ```json // Published file: pint.json { "preset": "laravel", "rules": { "declare_strict_types": true, "final_class": true, "ordered_class_elements": true, "strict_comparison": true, "no_unused_imports": true, "fully_qualified_strict_types": true } } ``` ```bash # Run Pint with the new configuration ./vendor/bin/pint # Options available: php artisan essentials:pint --force # Overwrite without confirmation php artisan essentials:pint --backup # Create backup as pint.json.backup ``` ## Essentials Rector Command Publishing opinionated Rector (refactoring tool) configuration ```bash php artisan essentials:rector --force --backup ``` ```php // Published file: rector.php use Rector\Config\RectorConfig; use Rector\Set\ValueObject\SetList; return RectorConfig::configure() ->withPaths([ __DIR__ . '/app', __DIR__ . '/tests', ]) ->withSets([ SetList::DEAD_CODE, SetList::CODE_QUALITY, SetList::TYPE_DECLARATION, SetList::PRIVATIZATION, SetList::EARLY_RETURN, SetList::STRICT_BOOLEANS, ]); ``` ```bash # Run Rector with the new configuration ./vendor/bin/rector process # Options available: php artisan essentials:rector --force # Overwrite without confirmation php artisan essentials:rector --backup # Create backup as rector.php.backup ``` ## Publishing Custom Stubs Customizing the stub files used by the package ```bash php artisan vendor:publish --tag=essentials-stubs ``` ```php // Published to: stubs/action.stub <?php declare(strict_types=1); namespace {{ namespace }}; use Illuminate\Support\Facades\DB; final readonly class {{ class }} { /** * Execute the action. */ public function handle(): void { DB::transaction(function (): void { // }); } } ``` ```bash # After customizing the stub, new actions use your template php artisan make:action ProcessPaymentAction # Uses your customized stubs/action.stub ``` ## Summary Laravel Essentials streamlines Laravel development by providing production-ready defaults that prevent common bugs and performance issues. The main use cases include enabling strict model behavior to catch errors early in development, automatically eager loading relationships to eliminate N+1 query problems, using immutable dates to prevent unexpected mutations, and enforcing HTTPS in production environments. The package also enhances testing workflows by preventing stray HTTP requests and faking sleep operations, while providing code quality tools through opinionated Pint and Rector configurations. Integration is seamless through Laravel's package auto-discovery - simply install via Composer and the service provider automatically configures all enabled features. Developers can customize behavior by publishing the configuration file and toggling individual configurables, or by defining environment-specific overrides for features like HTTPS enforcement. The package follows Laravel conventions and works alongside existing code without requiring changes to models or controllers. For teams seeking to standardize on best practices, the included Artisan commands help generate consistent action classes and enforce code quality standards across the project, making it an excellent foundation for new Laravel applications or a gradual improvement path for existing ones.