Skip to content

Instantly share code, notes, and snippets.

@stefanofago73
Last active April 18, 2022 16:07
Show Gist options
  • Save stefanofago73/6bdc4ca87d727f50b73a5bc62d9c8a04 to your computer and use it in GitHub Desktop.
Save stefanofago73/6bdc4ca87d727f50b73a5bc62d9c8a04 to your computer and use it in GitHub Desktop.
<?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