Skip to content

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

bash
php artisan make:specification UserActiveSpecification

This creates a basic specification at app/Specifications/UserActiveSpecification.php.

Command Signature

bash
php artisan make:specification {name} [options]

Arguments

  • name - The name of the specification class (required)

Naming Conventions

The command supports several naming patterns:

bash
# 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.

bash
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
php
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.

bash
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.

bash
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.

bash
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.

bash
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.

bash
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.

bash
php artisan make:specification ExistingSpecification --force

--inline

Create specification without domain folder structure.

bash
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).

bash
php artisan make:specification DataSpecification --type=query
php artisan make:specification MemorySpecification --type=collection
php artisan make:specification HybridSpecification --type=both

Complete Examples

bash
# 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

bash
# 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

bash
# 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
<?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
<?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:

bash
# Publish stubs to your application
php artisan vendor:publish --tag=specification-stubs

This publishes stubs to resources/stubs/specification/:

  • specification.stub - Basic specification template
  • specification.model.stub - Model-bound template
  • specification.composite.stub - Composite specification template
  • specification.cacheable.stub - Cacheable specification template
  • specification.builder.stub - Builder pattern template
  • specification.test.stub - PHPUnit test template
  • specification.pest.stub - Pest test template

Customizing a Stub

Edit resources/stubs/specification/specification.stub:

php
<?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:

bash
# 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

bash
# 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

bash
# 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

bash
# Error: Specification already exists!
# Solution: Use --force to overwrite
php artisan make:specification ExistingSpec --force

Invalid Model

bash
# Error: Model not found
# Solution: Ensure model exists or use full namespace
php artisan make:specification UserSpec --model=App\\Models\\User

Directory Permissions

bash
# 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:

  1. Go to Settings → Editor → File and Code Templates
  2. Add new template "Laravel Specification"
  3. Use the stub content as template

VS Code Snippets

Add to .vscode/php.code-snippets:

json
{
  "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

Released under the MIT License.