Download the PHP package gwangjinkim/php-multidispatch without Composer
On this page you can find all versions of the php package gwangjinkim/php-multidispatch. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download gwangjinkim/php-multidispatch
More information about gwangjinkim/php-multidispatch
Files in gwangjinkim/php-multidispatch
Package php-multidispatch
Short Description Simple and elegant multiple dispatch for PHP with hierarchy resolution.
License MIT
Informations about the package php-multidispatch
php-multidispatch: Multiple Dispatch (with CLOS Extensions) for PHP
A modern, readable, CLOS-inspired multiple dispatch library for PHP—now with support for :primary, :before, :after, :around, and call-next-method! Open-Closed Principle in action, no fuss.
- GitHub: gwangjinkim/php-multidispatch
- Packagist: gwangjinkim/php-multidispatch
What is Multiple Dispatch? (And Why Should You Care?)
Multiple dispatch lets you write functions whose behavior depends on the runtime types of all their arguments—not just the first one (like in classic OOP). Imagine polymorphism that’s not boxed into inheritance hierarchies, with the freedom to extend methods for new types, even across package boundaries.
Why is this awesome?
- Write cleaner, more declarative code (no tangled if-else or switch statements).
- Add new behaviors from outside existing packages—no patching or hacking core code.
- Follow the Open-Closed Principle: your code is open for extension, closed for modification.
- Real power: this is what makes Julia, CLOS (Common Lisp), and R so extensible.
Multiple Dispatch allows you to import a package (which uses Multiple Dispatch) and extend it without ever having to touch or change its internal code (tests, definitions), but just add more classes and more methods/functions. It allows you to follow open-closed principle which would be impossible with classical Java/C++ OOP systems.
Features
- True Multiple Dispatch (not just single dispatch)
- CLOS-style Method Combinations: :primary, :before, :after, :around, and
$callNext - Inheritance & Interface Awareness: Works with classes, interfaces, built-in types
- Fallbacks: Register wildcard methods for default cases
- Simple API: Intuitive, modern PHP code
- Configurable Dispatch Policy: Choose “first-wins” or “last-wins” for registration order.
Table of Contents
- Installation
- Classic Usage (No CLOS Extensions)
- CLOS Extensions: :primary, :before, :after, :around, and call-next-method
- Extended Example: CLOS in PHP
- Testing
- Troubleshooting
- Links & References
Installation
With Composer
Use :dev-main to get the newest version! Specify version numbers when you want to downgrade or pin a version.
Or add to your composer.json:
Eventually use "^0.3.1" e.g., to pin to a version.
Requirements
- PHP 8.1 or newer recommended
PHP Installation Shortcuts
- MacOS: See this detailed guide (insert your own article link here)
-
Linux (Ubuntu):
- Windows (with Scoop):
Dispatch Policy: first-wins vs last-wins
You control which matching handler "wins" when there are multiple equally-specific possibilities (for example, two interfaces, or multiple wildcards).
- First-wins: The first registered method for a type signature is chosen (classic OOP behavior).
- Last-wins: The last registered method is chosen (suits override-style patterns).
Default: last-wins for maximum extensibility, but you can switch any dispatcher at any time:
Use DispatchPolicy::FirstWins for backwards compatibility or stricter method resolution.
| Policy | Which handler wins? | When to use |
|---|---|---|
| first-wins | First registered | Strict/classic OOP, legacy, backward-compat |
| last-wins | Last registered (default) | Override style, plugin/extensible systems |
Classic Usage: Multiple Dispatch the Simple Way (No CLOS Extensions)
If you just want plain, classic multiple dispatch—no :before, :after, or :around—your code stays as simple and clean as before. Everything you knew still works, and it’s all backwards-compatible!
Here’s how you use the package the “old-school” way (like before CLOS extensions):
How it works:
- You register handlers for each type signature (single or multiple arguments, e.g. ['int', 'string']).
- On call, the dispatcher figures out the most specific match (based on type, class, interface, and inheritance).
- The handler runs.
- No CLOS extensions means there’s one winner, no call_next, and no :before/:after/:around stacking.
- This style is familiar if you know Python’s functools.singledispatch or Julia’s basic dispatch.
When to use:
- You want simple, one-winner dispatch logic.
- You’re porting code from a previous version of this package.
- You don’t need CLOS-style hooks or method chaining (yet).
Note: You can always choose whether registration order is first-wins or last-wins, per-dispatcher, using
setDispatchPolicy. The default islast-wins, but all older code is fully supported.
Why CLOS? (And What Makes It Different?)
Why all this talk about CLOS (the Common Lisp Object System)?
CLOS is the most advanced, flexible object system ever built—letting you combine, stack, override, and wrap behavior with surgical precision.
With these extensions, you can:
- Dynamically stack hooks before/after/around any method, for any type (logging, validation, timing, security, profiling, tracing, etc).
- Control composition: Choose which method(s) run and how their results are combined—no more black-box dispatch!
- Open-Closed Principle, but supercharged: Extend any package, for any type, without touching its code.
- Stay DRY: Cross-cutting concerns (security, logging, caching) are isolated, not tangled up in your logic.
It’s a friendlier, more composable way to program.
And it’s 100% optional—you can stick with classic style if you like!
CLOS-Style Method Combination
Inspired by the Common Lisp Object System (CLOS), you can now combine multiple method types:
- :primary – The main methods, as before
- :before – Run before the primaries (in specificity order)
- :after – Run after the primaries (in reverse specificity)
- :around – Can wrap everything (get
$callNextas first argument; call it to proceed) - call-next-method – Provided to :around methods as
$callNext(you must call it to continue the chain)
Registration Syntax:
Example:
Output:
How the Method Combination Works:
- All matching :before methods are called, from most specific to least.
- All :around methods wrap the chain (most specific is outermost).
- The most specific :primary method is called.
- All matching :after methods are called, from least specific to most.
You can combine :before, :after, :primary, and :around on any type signature.
Extended CLOS Example
Here is a full, extended example to clarify usage and show best practices—great for both CLOS and non-CLOS users.
What you'll see:
How to Think About Each Method Type:
- :primary: The "main event"—your usual handler, one per match.
- :before: Side-effects you want to happen before the main event, e.g., logging, setup, animation, etc.
- :after: Side-effects after the main event, e.g., cleanup, logging, summary.
- :around: Like a decorator or middleware: can do stuff before/after and even decide not to call the rest at all (by not calling
$callNext). - call-next-method: Only available inside :around. Lets you control the chain, e.g., by running or skipping underlying methods.
Detailed CLOS Example With Explanations
Output:
What’s happening?
- All hooks (:before, :after, :around) are run in the right order.
- $callNext in :around lets you run or skip the rest.
- You can combine as many hooks and layers as you want!
Pro tip: Want several :around? Just register more! They stack “outside-in” (the last registered is the innermost).
Testing
Run your tests with PHPUnit:
You’ll see all your dispatch rules and method combinations in action. Both classic and CLOS-style tests are included.
Troubleshooting
- Function not found errors? Make sure you've run
composer dump-autoloadand are loading viavendor/autoload.php. - Order of registration: If you register multiple methods for the same types, the most specific (class, subclass, interface) wins.
- :around method argument order:
$callNextmust come first.
If you get stuck, check out the examples or open an issue.
Links & References
- Official Packagist Package
- Project on GitHub
- Installing PHP with phpenv (detailed guide)
- Beyond if-else: Smarter function dispatch in PHP (Medium)
- CLOS on Wikipedia
- Julia Multiple Dispatch
Contributors / Authors
- Gwang-Jin Kim [email protected]
- David J. Schwarz [email protected]
Call to Action
Ready to write cleaner, more extensible PHP—no more “if-else soup”?
Try it out!
- Please star ⭐ the GitHub project!
- Try it out in your next side project
- File issues or request features or share feedback for improvements or contribute extensions
Whether you want classic dispatch, CLOS power features, or both, you’re covered.
Enjoy dispatching!