PHPackages                             chalcedonyt/laravel-specification - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. chalcedonyt/laravel-specification

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

chalcedonyt/laravel-specification
=================================

Implementation of the specification pattern

1.0.1(7y ago)128.6k6[1 issues](https://github.com/chalcedonyt/laravel-specification/issues)MITPHPPHP &gt;=5.3.0

Since Nov 13Pushed 7y ago2 watchersCompare

[ Source](https://github.com/chalcedonyt/laravel-specification)[ Packagist](https://packagist.org/packages/chalcedonyt/laravel-specification)[ Docs](https://github.com/chalcedonyt/laravel-specification)[ RSS](/packages/chalcedonyt-laravel-specification/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (2)Versions (3)Used By (0)

laravel-specification
=====================

[](#laravel-specification)

An adaptation of the Specification Pattern as done by , adding an artisan command to quickly create specifications.

Install
-------

[](#install)

Via Composer (please change your `minimum-stability` to "dev")

```
$ composer require chalcedonyt/laravel-specification
```

Then run `composer update`. Once composer is finished, add the service provider to the `providers` array in `app/config/app.php`:

```
Chalcedonyt\Specification\Providers\SpecificationServiceProvider::class

```

Generating Specifications
-------------------------

[](#generating-specifications)

An artisan command will be added to quickly create specifications.

```
php artisan make:specification [NameOfSpecification]
```

Adding a `--parameters` flag will prompts for parameters to be inserted into the constructor when generated:

```
Enter the class or variable name for parameter 0 (Examples: \App\User or $value) [Blank to stop entering parameters] [(no_param)]:
 > \App\User

 Enter the class or variable name for parameter 1 (Examples: \App\User or $value) [Blank to stop entering parameters] [(no_param)]:
 > $my_value

```

Results in

```
class NewSpecification extends AbstractSpecification
{

    /**
    * @var  \App\User
    */
    protected $user;

    /**
    * @var
    */
    protected $myValue;

    /**
    *
    *  @param  \App\User $user
    *  @param   $myValue
    *
    */
    public function __construct(\App\User $user, $my_value)
    {
        $this->user = $user;
        $this->myValue = $my_value;
    }

    /**
    * Tests an object and returns a boolean value
    *
    * @var  mixed
    */

    public function isSatisfiedBy($candidate)
    {
        //return a boolean value
    }

}
```

Usage
-----

[](#usage)

```
class AgeOfPersonSpecification extends \Chalcedonyt\Specification\AbstractSpecification
{

    protected $minAge;
    protected $maxAge;

    /**
    * Set properties here for a parameterized specification.
    *
    */
    public function __construct($min_age, $max_age)
    {
        $this->minAge = $min_age;
        $this->maxAge = $max_age;
    }

    /**
    * Tests an object and returns a boolean value
    *
    * @var Array $candidate
    */

    public function isSatisfiedBy($candidate)
    {
        return $this->minAge maxAge >= $candidate['age'];
    }

}
```

```
class MalePersonSpecification  extends \Chalcedonyt\Specification\AbstractSpecification
{
    const GENDER_MALE = 1;
    const GENDER_FEMALE = 2;

    /**
    * Tests an object and returns a boolean value
    *
    * @var Array candidate
    */

    public function isSatisfiedBy($candidate)
    {
        return $candidate['gender'] == self::GENDER_MALE;
    }
}
```

```
$adult_spec = new AgeOfPersonSpecification(21, 80);
$teenager_spec = new AgeOfPersonSpecification(13, 19);
$puberty_spec = new AgeOfPersonSpecification(15, 19);

$male_spec = new MalePersonSpecification;
$female_spec = new NotSpec($male_spec);

$young_teenage_female = ['age' => 13, 'gender' => MalePersonSpecification::GENDER_FEMALE ];
$teenage_female = ['age' => 15, 'gender' => MalePersonSpecification::GENDER_FEMALE ];
$adult_female = ['age' => 22, 'gender' => MalePersonSpecification::GENDER_FEMALE ];

$nested_female_spec =  $puberty_spec->andSpec( $teenager_spec->andSpec( $female_spec ) );
$this->assertEquals( $nested_female_spec->isSatisfiedBy( $teenage_female ), true );
$this->assertEquals( $nested_female_spec->isSatisfiedBy( $young_teenage_female ), false );

$any_young_female_spec = $female_spec->andSpec( $teenager_spec->orSpec( $puberty_spec ));
$this->assertEquals( $nested_female_spec->isSatisfiedBy( $teenage_female ), true );
$this->assertEquals( $nested_female_spec->isSatisfiedBy( $adult_female ), false );
```

You may also retrieve unfulfilled specifications via the `remainderUnsatisfiedBy` property

```
$any_age_spec = new AgeOfPersonSpecification(1, 80);

$male_spec = new MalePersonSpecification;
$female_spec = new NotSpec($male_spec);

$male = ['age' => 16, 'gender' => MalePersonSpecification::GENDER_MALE ];

$any_young_female_spec = new AndSpec( $female_spec, $any_age_spec );
$this->assertEquals( $any_young_female_spec->isSatisfiedBy( $male ), false );

//returns the $female_spec
$unfulfilled_spec =  $any_young_female_spec->remainderUnsatisfiedBy( $male );
$inverse_female_spec = new NotSpec( $unfulfilled_spec );
$this->assertEquals( $inverse_female_spec->isSatisfiedBy( $male ), true );
```

Change log
----------

[](#change-log)

- 0.4.4 You can now create a Specification inside a directory by specifying it in the classname, e.g. `php artisan make:specification MyDir\\MySpec`
- 0.4.2 Removed the `isSatisfiedBy` method from the abstract and interface. This allows type hinting on the $candidate.
- 0.4.1 Tweaked the generated views to use camel\_case on any parameters.
- 0.4 Updated console command. You may now specify constructor parameters for the specification generator by entering the `--parameters` flag
- 0.3 Removed functionality to type-hint the argument to isSatisfiedBy, as PHP doesn't allow overloading abstract methods.
- 0.2 Added `remainderUnsatisfiedBy` functions

Testing
-------

[](#testing)

Credits
-------

[](#credits)

- Dominic Liebler \[\]
- C# Specification Framework by Firzen \[\]
- The original Specification Pattern document by Eric Evans and Martin Fowler \[\]

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance18

Infrequent updates — may be unmaintained

Popularity28

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 76.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~996 days

Total

2

Last Release

2843d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/3ff150ccb744dbada2b6373b324071abc871ba07fc3334ece55860c35d36d124?d=identicon)[chalcedonyt](/maintainers/chalcedonyt)

---

Top Contributors

[![timothythteoh](https://avatars.githubusercontent.com/u/7899530?v=4)](https://github.com/timothythteoh "timothythteoh (10 commits)")[![chalcedonyt](https://avatars.githubusercontent.com/u/3726096?v=4)](https://github.com/chalcedonyt "chalcedonyt (2 commits)")[![mtdavidson](https://avatars.githubusercontent.com/u/201792?v=4)](https://github.com/mtdavidson "mtdavidson (1 commits)")

---

Tags

laravelspecificationspecification pattern

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/chalcedonyt-laravel-specification/health.svg)

```
[![Health](https://phpackages.com/badges/chalcedonyt-laravel-specification/health.svg)](https://phpackages.com/packages/chalcedonyt-laravel-specification)
```

###  Alternatives

[barryvdh/laravel-ide-helper

Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.

14.9k123.0M687](/packages/barryvdh-laravel-ide-helper)[interaction-design-foundation/laravel-geoip

Support for multiple Geographical Location services.

17221.0k3](/packages/interaction-design-foundation-laravel-geoip)[nedwors/navigator

A Laravel package to ease defining navigation menus

433.1k](/packages/nedwors-navigator)[xefi/faker-php-laravel

Faker php integration with laravel

1915.1k](/packages/xefi-faker-php-laravel)[dcblogdev/laravel-junie

Install pre-configured guides for Jetbrains Junie

392.5k](/packages/dcblogdev-laravel-junie)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
