make:specification Command
The make:specification
Artisan command generates specification classes with various templates and options, similar to Laravel's built-in generators like make:model
and make:controller
.
Basic Usage
php artisan make:specification UserActiveSpecification
This creates a basic specification at app/Specifications/UserActiveSpecification.php
.
Command Signature
php artisan make:specification {name} [options]
Arguments
name
- The name of the specification class (required)
Naming Conventions
The command supports several naming patterns:
# Simple specification
php artisan make:specification ActiveUserSpecification
# Domain/Module organization (recommended)
php artisan make:specification User/ActiveUserSpecification
php artisan make:specification Booking/AvailabilitySpecification
php artisan make:specification Product/Search/PriceRangeSpecification
# The command will create proper directory structure:
# app/Specifications/User/ActiveUserSpecification.php
# app/Specifications/Booking/AvailabilitySpecification.php
# app/Specifications/Product/Search/PriceRangeSpecification.php
Options
--model (-m)
Generate a specification bound to a specific model.
php artisan make:specification UserPremiumSpecification --model=User
Generated code includes:
- Model type hints in method signatures
- Model import statement
- Model-specific variable names in documentation
public function isSatisfiedBy(mixed $candidate): bool
{
if (!$candidate instanceof User) {
return false;
}
// TODO: Implement your User business rule logic here
return false;
}
--composite (-c)
Create a composite specification with example composition structure.
php artisan make:specification ComplexFilterSpecification --composite
Generated code includes:
- Array to hold child specifications
- Methods to add/remove specifications
- Iteration logic for applying all specifications
--cacheable
Include the CacheableSpecification trait for caching support.
php artisan make:specification ExpensiveCalculationSpecification --cacheable
Generated code includes:
- CacheableSpecification trait usage
- Cache TTL configuration
- Cache key generation methods
- Cache clearing methods
--builder (-b)
Generate specification using the builder pattern.
php artisan make:specification AdvancedSearchSpecification --builder
Generated code includes:
- SpecificationBuilder instance
- Fluent building methods
- Builder configuration in constructor
--test (-t)
Generate an accompanying PHPUnit test.
php artisan make:specification OrderSpecification --test
Creates:
app/Specifications/OrderSpecification.php
tests/Unit/Specifications/OrderSpecificationTest.php
--pest
Generate an accompanying Pest test instead of PHPUnit.
php artisan make:specification ProductSpecification --pest
Creates:
app/Specifications/ProductSpecification.php
tests/Unit/Specifications/ProductSpecificationTest.php
(Pest format)
--force (-f)
Overwrite the specification if it already exists.
php artisan make:specification ExistingSpecification --force
--inline
Create specification without domain folder structure.
php artisan make:specification User/InlineSpecification --inline
Creates: app/Specifications/InlineSpecification.php
(ignores User/
prefix)
--type
Specify the type of specification (query, collection, or both).
php artisan make:specification DataSpecification --type=query
php artisan make:specification MemorySpecification --type=collection
php artisan make:specification HybridSpecification --type=both
Complete Examples
E-commerce Product Search
# Generate the main composite specification
php artisan make:specification Product/ProductSearchSpecification --composite --cacheable
# Generate individual specifications
php artisan make:specification Product/PriceRangeSpecification --model=Product
php artisan make:specification Product/CategorySpecification --model=Product
php artisan make:specification Product/AvailabilitySpecification --model=Product
php artisan make:specification Product/RatingSpecification --model=Product --test
User Management System
# Generate with model binding and test
php artisan make:specification User/ActiveUserSpecification --model=User --test
# Generate composite for complex permissions
php artisan make:specification User/Permission/AccessControlSpecification --composite --model=User
# Generate with caching for expensive checks
php artisan make:specification User/VipStatusSpecification --model=User --cacheable
Report Generation
# Main report specification with builder pattern
php artisan make:specification Report/SalesReportSpecification --builder --cacheable
# Date range specification
php artisan make:specification Report/DateRangeSpecification --cacheable
# Customer segment specification
php artisan make:specification Report/CustomerSegmentSpecification --composite
Generated File Structure
Basic Specification
<?php
namespace App\Specifications;
use DangerWayne\Specification\Specifications\AbstractSpecification;
use Illuminate\Database\Eloquent\Builder;
class UserActiveSpecification extends AbstractSpecification
{
/**
* Create a new specification instance.
*/
public function __construct()
{
//
}
/**
* Determine if the candidate satisfies the specification.
*
* @param mixed $candidate
* @return bool
*/
public function isSatisfiedBy(mixed $candidate): bool
{
// TODO: Implement your business rule logic here
// Example: return $candidate->status === 'active';
return false;
}
/**
* Apply the specification to a query builder.
*
* @param Builder $query
* @return Builder
*/
public function toQuery(Builder $query): Builder
{
// TODO: Implement your query logic here
// Example: return $query->where('status', 'active');
return $query;
}
/**
* Get the specification parameters for cache key generation.
*
* @return array<string, mixed>
*/
protected function getParameters(): array
{
return [
// Add any constructor parameters here for caching
];
}
}
Model-Bound Specification
When using --model=User
:
<?php
namespace App\Specifications\User;
use App\Models\User;
use DangerWayne\Specification\Specifications\AbstractSpecification;
use Illuminate\Database\Eloquent\Builder;
class ActiveUserSpecification extends AbstractSpecification
{
/**
* Determine if the user satisfies the specification.
*
* @param mixed $candidate
* @return bool
*/
public function isSatisfiedBy(mixed $candidate): bool
{
if (!$candidate instanceof User) {
return false;
}
// TODO: Implement your User business rule logic here
return false;
}
/**
* Apply the specification to a User query builder.
*
* @param Builder<User> $query
* @return Builder<User>
*/
public function toQuery(Builder $query): Builder
{
// TODO: Implement your User query logic here
return $query;
}
}
Customizing Stubs
You can customize the generated specifications by publishing and modifying the stubs:
# Publish stubs to your application
php artisan vendor:publish --tag=specification-stubs
This publishes stubs to resources/stubs/specification/
:
specification.stub
- Basic specification templatespecification.model.stub
- Model-bound templatespecification.composite.stub
- Composite specification templatespecification.cacheable.stub
- Cacheable specification templatespecification.builder.stub
- Builder pattern templatespecification.test.stub
- PHPUnit test templatespecification.pest.stub
- Pest test template
Customizing a Stub
Edit resources/stubs/specification/specification.stub
:
<?php
namespace {{ namespace }};
use DangerWayne\Specification\Specifications\AbstractSpecification;
use Illuminate\Database\Eloquent\Builder;
// Add your custom imports
class {{ class }} extends AbstractSpecification
{
// Add your custom properties
public function __construct()
{
// Your custom initialization
}
// Your methods...
}
Best Practices
1. Use Domain Organization
Organize specifications by domain or module:
# Good: Clear domain organization
php artisan make:specification Order/Shipping/ExpressShippingSpecification
php artisan make:specification Order/Payment/CreditCardSpecification
php artisan make:specification Order/Validation/OrderValidSpecification
# Less organized: Flat structure
php artisan make:specification ExpressShippingOrderSpecification
php artisan make:specification CreditCardPaymentSpecification
2. Combine Options Intelligently
# Model-bound with test for critical business logic
php artisan make:specification Order/HighValueOrderSpecification --model=Order --test
# Composite with caching for complex aggregations
php artisan make:specification Report/ExecutiveDashboardSpecification --composite --cacheable
# Builder pattern for user-configurable filters
php artisan make:specification Search/AdvancedSearchSpecification --builder --model=Product
3. Follow Naming Conventions
# Use descriptive, specific names
php artisan make:specification User/EmailVerifiedSpecification # Good
php artisan make:specification User/CheckSpecification # Too vague
# Use domain context
php artisan make:specification Booking/AvailableSlotSpecification # Good
php artisan make:specification AvailableSpecification # Lacks context
Troubleshooting
Class Already Exists
# Error: Specification already exists!
# Solution: Use --force to overwrite
php artisan make:specification ExistingSpec --force
Invalid Model
# Error: Model not found
# Solution: Ensure model exists or use full namespace
php artisan make:specification UserSpec --model=App\\Models\\User
Directory Permissions
# Error: Unable to create directory
# Solution: Check permissions
chmod -R 755 app/Specifications
Integration with IDE
PHPStorm File Template
Create a file template in PHPStorm for quick specification creation:
- Go to Settings → Editor → File and Code Templates
- Add new template "Laravel Specification"
- Use the stub content as template
VS Code Snippets
Add to .vscode/php.code-snippets
:
{
"Laravel Specification": {
"prefix": "spec",
"body": [
"<?php",
"",
"namespace App\\Specifications\\${1:Domain};",
"",
"use DangerWayne\\Specification\\Specifications\\AbstractSpecification;",
"use Illuminate\\Database\\Eloquent\\Builder;",
"",
"class ${2:Name}Specification extends AbstractSpecification",
"{",
" public function isSatisfiedBy(mixed \\$candidate): bool",
" {",
" ${3:// Implementation}",
" }",
" ",
" public function toQuery(Builder \\$query): Builder",
" {",
" ${4:// Implementation}",
" }",
"}"
]
}
}
See Also
- Quick Start Guide - Getting started with the generator
- AbstractSpecification - Base class reference
- SpecificationBuilder - Builder pattern usage
- Testing Specifications - Testing best practices