Last active
April 18, 2022 16:07
-
-
Save stefanofago73/6bdc4ca87d727f50b73a5bc62d9c8a04 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php declare(strict_types = 1); | |
// ==================================================================== | |
// | |
// Copy and Paste on https://3v4l.org/ | |
// PHPStan & Psalm verified... | |
// Some code isn't the best but I want to transmit the ideas! | |
// | |
// ==================================================================== | |
// | |
// Singleton... The anti-pattern! | |
// | |
enum DBFacade | |
{ | |
case INSTANCE; | |
function connection():void | |
{ | |
} | |
} | |
DBFacade::INSTANCE->connection(); | |
// ============================================================================== | |
// ============================================================================== | |
// | |
// Empty Enum... | |
// or Commodity Element... The anti-pattern! | |
// | |
enum Calculator | |
{ | |
static function sum(int $a,int $b):int | |
{ | |
return $a+$b; | |
} | |
} | |
Calculator::sum(1,2); | |
// ============================================================================== | |
// ============================================================================== | |
// | |
// Event Masking... | |
// Using backed enum with boolean operators | |
// | |
enum EventType:int | |
{ | |
case CLICKED=1; | |
case FOCUSED=2; | |
case EXECUTED=4; | |
case BLURRED=8; | |
static function eventsMask(EventType ... $type): int | |
{ | |
$values = array_map(fn(EventType $eventType)=>$eventType->value,$type); | |
return (int) array_reduce($values, | |
/** | |
* @param int|null $carry | |
* @param int $val | |
* @return int */ fn($carry,$val)=> $carry===null?$val: ($carry | $val) | |
); | |
} | |
} | |
echo 'mask: '.EventType::eventsMask(EventType::CLICKED, | |
EventType::FOCUSED, | |
EventType::EXECUTED, | |
EventType::BLURRED).PHP_EOL; | |
// ============================================================================== | |
// ============================================================================== | |
// | |
// Keys To Functions... with FP touch... | |
// | |
enum Operation:int | |
{ | |
case SUM=1; | |
case SUB=2; | |
case MUL=3; | |
case DIV=4; | |
/** @return callable(Operation):callable(int,int):int **/ | |
static function processorsMap():callable | |
{ | |
$processors = array( | |
Operation::SUM->value =>fn(int $a, int $b):int=>$a+$b, | |
Operation::SUB->value =>fn(int $a, int $b):int=>$a-$b, | |
Operation::MUL->value =>fn(int $a, int $b):int=>$a*$b, | |
Operation::DIV->value =>fn(int $a, int $b):int=>(int)($a/$b), | |
); | |
/** @psalm-suppress PossiblyUndefinedIntArrayOffset */ | |
return fn(Operation $opKey)=>$processors[$opKey->value]; | |
} | |
} | |
$processors = Operation::processorsMap(); | |
echo $processors(Operation::SUM)(1,3); | |
echo PHP_EOL; | |
// ============================================================================== | |
// ============================================================================== | |
// | |
// State Machine! | |
// Very basic example... | |
// | |
enum PeachesPipe | |
{ | |
case WASH; | |
case PEEL; | |
case CUT; | |
case PUT_IN_JAR; | |
case READY; | |
function process():PeachesPipe | |
{ | |
/** @var callable():PeachesPipe $call */ | |
$call = [$this,$this->name]; | |
return $call(); | |
} | |
private function WASH():PeachesPipe | |
{ | |
echo $this->name.PHP_EOL; | |
return PeachesPipe::PEEL; | |
} | |
private function PEEL():PeachesPipe | |
{ | |
echo $this->name.PHP_EOL; | |
return PeachesPipe::CUT; | |
} | |
private function CUT():PeachesPipe | |
{ | |
echo $this->name.PHP_EOL; | |
return PeachesPipe::PUT_IN_JAR; | |
} | |
private function PUT_IN_JAR():PeachesPipe | |
{ | |
echo $this->name.PHP_EOL; | |
return PeachesPipe::READY; | |
} | |
} | |
$pipeline = PeachesPipe::WASH; | |
while($pipeline !== PeachesPipe::READY) | |
{ | |
$pipeline = $pipeline->process(); | |
} | |
// ============================================================================== | |
// ============================================================================== | |
// | |
// Factory...with backed enum! | |
// Using some feature of PHP 8.1 | |
// | |
final class Topping implements Stringable | |
{ | |
function __construct(public readonly string $name){} | |
function __toString():string | |
{ | |
return 'Topping('.$this->name.')'; | |
} | |
} | |
final class Cake implements Stringable | |
{ | |
function __construct(public readonly CakeType $type, | |
public readonly Topping $top, | |
public readonly int $weight){} | |
function __toString():string | |
{ | |
return 'Cake('.$this->type->name.','.$this->top.', '.$this->weight.')'; | |
} | |
} | |
interface CakeFactory | |
{ | |
function create():Cake; | |
} | |
enum CakeType:int implements CakeFactory | |
{ | |
case CHOCOLATE=2000; | |
case VANILLA=2200; | |
case FROSTED=2500; | |
function create():Cake | |
{ | |
return match($this) | |
{ | |
CakeType::CHOCOLATE=>new Cake($this,new Topping('Glazed Choco'),$this->value), | |
CakeType::VANILLA=>new Cake($this,new Topping('Glazed White'),$this->value), | |
CakeType::FROSTED=>new Cake($this,new Topping('Cherries'),$this->value), | |
}; | |
} | |
} | |
echo CakeType::VANILLA->create(); | |
echo PHP_EOL; | |
// ============================================================================== | |
// ============================================================================== | |
// | |
// Strategy Pattern | |
// Backed enum and static function... | |
enum Currency | |
{ | |
case EUR; | |
case USD; | |
} | |
final class Item implements Stringable | |
{ | |
function __construct(public readonly string $id, | |
public readonly int $quantity, | |
public readonly int $price, | |
public readonly Currency $currency){} | |
function __toString():string | |
{ | |
return '[ id:'.$this->id. | |
', quantity: '.$this->quantity. | |
', price:'.$this->price.' '.$this->currency->name.' ]'; | |
} | |
} | |
final class Basket implements Stringable | |
{ | |
/** @param list<Item> $items **/ | |
function __construct(private array $items){} | |
/** @return list<Item> **/ | |
function items():array | |
{ | |
return $this->items; | |
} | |
function __toString():string | |
{ | |
return '(Basket: '.var_export($this->items,true).')'; | |
} | |
} | |
enum DiscountType:int | |
{ | |
case BRONZE=5; | |
case SILVER=10; | |
case GOLD=15; | |
static function apply(Basket $basket, DiscountType $discount):Basket | |
{ | |
$factor = $discount->value/100; | |
$items = array_map( | |
fn(Item $item)=> | |
new Item($item->id, | |
$item->quantity, | |
($item->price - (int)($item->price*$factor)), | |
$item->currency), | |
$basket->items() | |
); | |
return new Basket($items); | |
} | |
} | |
$items = array( | |
new Item('az123',2,100,Currency::EUR), | |
new Item('azBCV',5,200,Currency::EUR), | |
new Item('azKJI',1,150,Currency::EUR), | |
); | |
$basket = new Basket($items); | |
$basket = DiscountType::apply($basket,DiscountType::BRONZE); | |
echo $basket.PHP_EOL; | |
// ============================================================================== | |
// ============================================================================== |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment