- var_dump: documentation ( source)
<?php
function sql(callable $expr): array
{
if ($context = (new \ReflectionFunction($expr))->getClosureThis()) {
$placeholder = new class($context) {
private object $context;
private ReflectionObject $reflection;
public function __construct(object $context) {
$this->context = $context;
$this->reflection = new \ReflectionObject($context);
}
public function __call($method, $args)
{
$method = $this->reflection->getMethod($method);
return $method->getClosure($this->context)->call($this->context, ...$args);
}
public function __get($property)
{
$property = $this->reflection->getProperty($property);
$property->setAccessible(true);
return $property->getValue($this->context);
}
public function __isset($property): bool
{
return $this->reflection->hasProperty($property);
}
public function __set($property, $value): void
{
$property = $this->reflection->getProperty($property);
$property->setAccessible(true);
$property->setValue($this->context, $value);
}
public function __toString(): string {
return '?';
}
};
} else {
$placeholder = new class {
public function __toString(): string {
return '?';
}
};
}
$expr = Closure::fromCallable($expr)
->bindTo($placeholder, $placeholder);
$params = [];
$generator = $expr();
while ($generator->valid()) {
$params[] = $generator->current(); // Get the value from "yield"
$generator->send('this'); // Insert placeholder
}
return [$generator->getReturn(), $params];
}
class Foo {
private int $id = 42;
public function bar(): void {
[$query, $params] = sql(fn() => "SELECT * FROM users WHERE id = ${yield $this->id} OR username = ${yield $this->username()}");
var_dump(
$query,
$params,
);
}
private function username(): string {
return 'azjezz';
}
}
$f = new Foo();
$f->bar();