rikta / callback-switch
Switch-statement-like objects based on callbacks for several use-cases
Requires
- php: >=7.4
- ext-json: *
Requires (Dev)
- mockery/mockery: ^1.4
- phpstan/phpstan: ^0.12
- phpstan/phpstan-mockery: ^0.12.7
- phpstan/phpstan-phpunit: ^0.12
- phpunit/phpunit: ^9.4
- roave/security-advisories: dev-master
- squizlabs/php_codesniffer: ^3.5
This package is auto-updated.
Last update: 2024-11-10 09:48:30 UTC
README
Advanced switch statements as classes
Description
This package provides classes that wrap similar logic to a switch statement into object-instances.
You provide several callbacks together with their key and subsequently call the instance like a method. (there is also a static one-method-call)
This enables you to abstract away commonly used switching-logic, dynamically construct the cases or maybe even inject some conditional as dependency e.g. in DI or Strategy-Patterns
Along the Abstraction this package ships:
SwitchByIsA
-> Keys are Interfaces (FQCN), prioritized by order of added callbacks (first wins)SwitchByType
-> Keys are inbuilt types or FQCNs, FQCNs have higher prioritySwitchByValue
-> Keys are the valuesSwitchBySubstring
-> Keys are substrings of the passed value; prioritized by order of added callbacks (first wins)
You can also easily implementing your own CallbackSwitches by extending the AbstractCallbackSwitch
and implementing the only abstract method to choose which callback to use
Installation
Require this package with composer require rikta/callback-switch
Usage
Cases
Regardless of your concrete call you provide your cases as callables
with an associated key.
The callable
will get the $value
as first parameter, and ...$extra
for the rest of it.
What you have to choose for the key depends on the type of switch you are using.
e.g. if you use SwitchByValue
it must match the exact (string)$value
,
if you use SwitchByType
it must match the type or class of $value
with Instance
Create
You can create a class implementing CallbackSwitch
with an optional ['key' => fn($value, ...$extra)]
array.
$exampleSwitch = new SwitchByType([ SwitchByType::string => staticfn($value) => ('Hello ' . $value), SwitchByType::int => staticfn($value) => ('Hello Agent '. $value), ])
Add Cases
You can add cases to a CallbackSwitchInstance with addCase($key, $callable)
$exampleSwitch->addCase(SwitchByType::array, fn($value) => ('Hello ' . implode(' and ', $value)))
Make optional
By default, a CallbackSwitch
shall throw an exception if neither a matching case was found, nor a default was provided.
If you mark the instance as "optional" null
will be returned instead.
There are two ways to mark an instance as optional:
- You can pass
true
as second argument to the constructor
$exampleSwitch = new SwitchByType([...], true)
- You can call
setOptional()
on the instance
$exampleSwitch->setOptional()
Invoke
Every class implementing SwitchCallback
is invokable, as if it would be a method.
Pass your $value
as first parameter, it will be used to determine the case and passed to the callback.
Any extraneous parameters you pass here will be passed to the callback as well.
echo $exampleSwitch(['Anna', 'Bob']);
Full example
$exampleSwitch = new SwitchByType([ SwitchByType::string => staticfn($value) => ('Hello ' . $value), SwitchByType::int => staticfn($value) => ('Hello Agent '. $value), ]); $exampleSwitch ->addCase(SwitchByType::array, fn($value) => ('Hello ' . implode(' and ', $value))) ->setOptional(); echo $exampleSwitch('World'); // Hello World echo $exampleSwitch(['Jay', 'Bob']); // Hello Jay and Bob echo $exampleSwitch(47); // Hello Agent 47
without Instance
If you need the CallbackSwitch only once, you can call the static version.
$value = 'World'; echo SwitchByType::switch($value, [ SwitchByType::string => staticfn($value) => ('Hello ' . $value), SwitchByType::int => staticfn($value) => ('Hello Agent '. $value), SwitchByType::array => staticfn($value) => ('Hello ' . implode(' and ', $value))) ]) // Hello World;
Make optional
By default, a CallbackSwitch
shall throw an exception if neither a matching case was found, nor a default was provided.
If you call ::switchOptional
instead of ::switch
, null
will be returned instead.
Contributing
Contributions are always welcome.
Should you want to contribute I suggest you take a look at CONTRIBUTING.md first.