Last active
December 30, 2022 06:34
-
-
Save denistouch/f99a44016317835c0eb26456c2142e3c to your computer and use it in GitHub Desktop.
Разбор query параметров в модель при помощи атрибутов в php 8
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 | |
namespace App\Controller; | |
use App\Attribute\QueryString; | |
use App\Attribute\RequestBody; | |
use App\Entity\Lesson; | |
use App\Entity\Studio; | |
use App\Model\ErrorResponse; | |
use App\Model\LessonChangeRequest; | |
use App\Model\LessonCreateRequest; | |
use App\Model\LessonItem; | |
use App\Model\LessonListRequest; | |
use App\Model\LessonListResponse; | |
use App\Model\OkResponse; | |
use App\Model\RepeatRequest; | |
use App\Service\AccessService; | |
use App\Service\LessonService; | |
use Nelmio\ApiDocBundle\Annotation\Model; | |
use OpenApi\Annotations as OA; | |
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; | |
use Symfony\Component\HttpFoundation\Response; | |
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | |
use Symfony\Component\Routing\Annotation\Route; | |
use Symfony\Component\Translation\TranslatableMessage; | |
class LessonController extends BaseController | |
{ | |
public function __construct( | |
private readonly LessonService $lessonService, | |
private readonly AccessService $accessService, | |
) { | |
} | |
/** | |
* Получение списка | |
* @OA\Tag(name="Занятия") | |
* @OA\Parameter(in="query",name="timezone", description="Временная зона", required=true) | |
* @OA\Parameter(in="query",name="startDate", description="Дата начала интервала", required=true) | |
* @OA\Parameter(in="query",name="endDate", description="Дата конца интервалла", required=true) | |
* @OA\Response( | |
* response=200, | |
* description="Список занятий", | |
* @Model(type=LessonListResponse::class) | |
* ) | |
* @OA\Response( | |
* response="404", | |
* description="Студия не найдена", | |
* @Model(type=ErrorResponse::class) | |
* ) | |
*/ | |
#[Route(path: '/api/v1/lessons/for-studio/{studio}', methods: ['GET'])] | |
#[ParamConverter('studio', options: ['mapping' => ['studio' => 'code']])] | |
public function getLessons(?Studio $studio, #[QueryString] LessonListRequest $request): Response | |
{ | |
if (!$this->accessService->canAccessAsManager($this->getUser(), $studio) && | |
!$this->accessService->canAccessAsTeacher($this->getUser(), $studio)) { | |
throw new NotFoundHttpException(new TranslatableMessage('studio.not_found')); | |
} | |
return $this->json($this->lessonService->getByRequestAndStudio($request, $studio)); | |
} | |
} |
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 | |
namespace App\Exception; | |
use RuntimeException; | |
use Symfony\Component\Translation\TranslatableMessage; | |
use Throwable; | |
class QueryParameterConvertException extends RuntimeException | |
{ | |
public function __construct(Throwable $previous = null) | |
{ | |
parent::__construct(new TranslatableMessage('query.exception'), 0, $previous); | |
} | |
} |
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 | |
namespace App\ArgumentResolver; | |
use App\Attribute\QueryString; | |
use App\Exception\QueryParameterConvertException; | |
use App\Exception\ValidationException; | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; | |
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; | |
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; | |
use Symfony\Component\Validator\Validator\ValidatorInterface; | |
class QueryParametersResolver implements ArgumentValueResolverInterface | |
{ | |
public function __construct( | |
private readonly ObjectNormalizer $normalizer, | |
private readonly ValidatorInterface $validator | |
) { | |
} | |
public function supports(Request $request, ArgumentMetadata $argument): bool | |
{ | |
return count($argument->getAttributes(QueryString::class, ArgumentMetadata::IS_INSTANCEOF)) > 0; | |
} | |
public function resolve(Request $request, ArgumentMetadata $argument): iterable | |
{ | |
try { | |
$model = $this->normalizer->denormalize($request->query->all(),$argument->getType()); | |
} catch (\Throwable $throwable) { | |
throw new QueryParameterConvertException($throwable); | |
} | |
$errors = $this->validator->validate($model); | |
if (count($errors) > 0) { | |
throw new ValidationException($errors); | |
} | |
yield $model; | |
} | |
} |
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 | |
namespace App\Attribute; | |
use Attribute; | |
#[Attribute(Attribute::TARGET_PARAMETER)] | |
class QueryString | |
{ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment