I’m a big fan of Haskell and one of my favorite feature of this awesome language is pattern matching. If you don’t know what’s pattern matching, it’s this:

The main advantage is, if I add a possibility in my type, for example data Customer = Student | Individual | Company, the Haskell compiler will tell me that my function is missing a pattern. I will need to provide a getPrice Company = ?.

Of course, in PHP we don’t have a compiler but we can still have some checks…

The problem

Imagine I have a class for my customer:

By the way, pay attention of how 4 lines of code became 18 lines. But, of course, Haskell is a incomprehensible language ;-)

If I have my unit tests like these:

If latter, I add a new type const COMPANY = 'company' in my class, my tests will remain green. If I use this if() {} elseif () {} else {} in a lot of places, it will be difficult to catch all occurrences.

The solution

Use my small pattern matching library (or build your own, it’s only a mater of hours…):

If I add a new type and I change my enumerate definition in one place new Pattern([self::STUDENT, self::INDIVIDUAL, self::COMPANY]), my previous tests are now failing with a new exception:

Even if, I never wrote a test to check if the price for a company is correct.

Extra features of my library

You can check the test file for all features.


My match() function is three simple checks happening every time. It means, it raises an exception even if the pattern could be resolved.


If your application is doing expensive work for each pattern (more expensive than returning “10” or “30”), you can wrap the result in a callback:

Callbacks arguments

And you can also give arguments to your callbacks with with:

Even if, in this case, you could simply use $this->age inside the callback.