Created
July 7, 2025 16:45
-
-
Save cizordj/9b2fdf1014fd0fbdcd677de93d64fa83 to your computer and use it in GitHub Desktop.
Case builder for Doctrine
This file contains hidden or 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); | |
interface WhenClauseInterface | |
{ | |
public function then(string $result): CaseBuilder; | |
} | |
use Ds\Vector; | |
use function implode; | |
use InvalidArgumentException; | |
final class CaseBuilder | |
{ | |
/** | |
* @var Vector<array{when: string, then: string}> $whenClauses | |
*/ | |
public readonly Vector $whenClauses; | |
private ?string $elseClause; | |
private ?string $caseExpression; | |
private function __construct() | |
{ | |
$this->whenClauses = new Vector(); | |
$this->elseClause = null; | |
$this->caseExpression = null; | |
} | |
public static function new(): static | |
{ | |
return new self(); | |
} | |
public static function expression(string $expression): static | |
{ | |
$new = new self(); | |
$new->caseExpression = $expression; | |
return $new; | |
} | |
public function when(string $condition): WhenClauseInterface | |
{ | |
return new class($this, $condition) implements WhenClauseInterface { | |
public function __construct( | |
private CaseBuilder $caseBuilder, | |
private string $condition | |
) {} | |
public function then(string $result): CaseBuilder | |
{ | |
$new = clone $this->caseBuilder; | |
$new->whenClauses = $this->caseBuilder->whenClauses->copy(); | |
$new->whenClauses->push(['when' => $this->condition, 'then' => $result]); | |
return $new; | |
} | |
}; | |
} | |
public function else(string $result): static | |
{ | |
$new = clone $this; | |
$new->elseClause = $result; | |
return $new; | |
} | |
public function build(): string | |
{ | |
if ($this->whenClauses->isEmpty()) { | |
throw new InvalidArgumentException( | |
'CASE statement must have at least one WHEN clause' | |
); | |
} | |
$parts = []; | |
if ($this->caseExpression !== null) { | |
$parts[] = "CASE {$this->caseExpression}"; | |
} else { | |
$parts[] = 'CASE'; | |
} | |
foreach ($this->whenClauses as $clause) { | |
$parts[] = "WHEN {$clause['when']} THEN '{$clause['then']}'"; | |
} | |
if ($this->elseClause !== null) { | |
$parts[] = "ELSE '{$this->elseClause}'"; | |
} | |
$parts[] = 'END'; | |
return implode(' ', $parts); | |
} | |
} | |
// Usage: | |
$foo = CaseBuilder::new() | |
->when('permissao.id = 1') | |
->then('true') | |
->else('false') | |
->build(); | |
// CASE WHEN permission.id = 1 THEN 'true' ELSE 'false' END | |
$bar = CaseBuilder::expression('permission.id') | |
->when('1') | |
->then('Foo') | |
->when('2') | |
->then('Bar') | |
->else('unknown') | |
->build(); | |
// CASE permission.id WHEN 1 THEN 'Foo' WHEN 2 THEN 'Bar' ELSE 'unknown' END |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment