Skip to content

Instantly share code, notes, and snippets.

@BoShurik
Created May 8, 2024 21:16
Show Gist options
  • Save BoShurik/03aea5a2f374e35b2274a010b596892f to your computer and use it in GitHub Desktop.
Save BoShurik/03aea5a2f374e35b2274a010b596892f to your computer and use it in GitHub Desktop.
Simple Yii ParametersResolver
<?php
namespace App\Model;
use App\Model\Attributes\FromBody;
use App\Model\Attributes\FromQuery;
use App\Model\Attributes\FromRequest;
use App\Model\Attributes\Model;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ServerRequestInterface;
use Webmozart\Assert\Assert;
use Yiisoft\Hydrator\HydratorInterface;
use Yiisoft\Middleware\Dispatcher\ParametersResolverInterface;
use Yiisoft\Validator\ValidatorInterface;
class ModelParameterResolver implements ParametersResolverInterface
{
public function __construct(
private HydratorInterface $hydrator,
private ValidatorInterface $validator
) {
}
public function resolve(array $parameters, ServerRequestInterface $request): array
{
$result = [];
foreach ($parameters as $parameter) {
$type = $parameter->getType();
if (!$type instanceof \ReflectionNamedType || $type->isBuiltin()) {
continue;
}
$attributes = $parameter->getAttributes(Model::class, \ReflectionAttribute::IS_INSTANCEOF);
if ($attributes === []) {
continue;
}
$class = $type->getName();
/** @var \ReflectionAttribute $attribute */
$attribute = current($attributes);
$attribute = $attribute->newInstance();
$data = match ($attribute::class) {
FromBody::class => $this->getBodyData($request),
FromRequest::class => (array) $request->getParsedBody(),
FromQuery::class => $request->getQueryParams(),
};
$value = $this->hydrator->create($class, $data);
if ($attribute->validate) {
$violations = $this->validator->validate($value);
if (!$violations->isValid()) {
throw new ViolationException($violations);
}
}
$result[$parameter->getName()] = $value;
}
return $result;
}
private function getBodyData(RequestInterface $request): array
{
$data = json_decode($request->getBody()->getContents(), true);
Assert::isArray($data);
return $data;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment