Пользовательский метод аннотации с вставкой параметра symfony 3.2

Итак, цель состоит в том, чтобы создать пользовательскую аннотацию, которая также могла бы вставить параметр в метод. Итак, после нескольких часов поиска решения и попытки заставить его работать, я так и не нашел полного решения, поэтому я собрал несколько из того, что смог найти, и мой код выглядит так:

public function onKernelController(FilterControllerEvent $event)
{
if (!is_array($controller = $event->getController())){
return;
}

$request = $event->getRequest();
$content = $request->getContent();
$data = json_decode($content,true);

$reflectionObject = new \ReflectionObject($controller[0]);
$reflectionMethod = $reflectionObject->getMethod($controller[1]);
$methodAnnotation = $this->reader->getMethodAnnotation($reflectionMethod, CheckRequest::class);
if(!$methodAnnotation){
return;
}
$propertyName = $methodAnnotation->getName();

try{
if ($request->getContentType() !== 'json' ) {
throw new ControlerNotAvailableException();
}

if(empty($content)){
throw new ControlerNotAvailableException();
}

if(empty($data) || !array_key_exists('type', $data)) {
throw new ControlerNotAvailableException();
}
}catch(ControlerNotAvailableException $e){
}

foreach($reflectionMethod->getParameters() as $param){
if($param->getName() !== $propertyName){
continue;
}
if($request->attributes->has($propertyName)){
return;
}
$request->attributes->set($propertyName, $data);
}
}

И мой класс аннотаций выглядит так:

class CheckRequest
{
private $name;

public function __construct($options)
{
if(isset($options['value'])){
$options['name'] = $options['value'];
unset($options['value']);
}
foreach ($options as $key => $value){
if(!property_exists($this, $key)){
throw new \InvalidArgumentException(sprintf('Property %s does not exist', $key));
}
$this->$key = $value;
}
}/**
* @return mixed
*/
public function getName()
{
return $this->name;
}

/**
* @param mixed $name
*/
public function setName($name)
{
$this->name = $name;
}
}

Поэтому, чтобы сделать эту вещь немного более понятной. У меня есть событие слушателя, которое слушает событие kernel.controller. В этом слушателе я запускаю несколько маленьких чаков, например, если тип контента — json и т. Д. Кроме того, ControllerNotAvailableEception это пользовательское исключение, которое я сделал, так что не позволяйте этому сбить вас с толку. Затем мы переходим к той части, где лежит мой вопрос, а именно:

foreach($reflectionMethod->getParameters() as $param){
if($param->getName() !== $propertyName){
continue;
}
if($request->attributes->has($propertyName)){
return;
}
$request->attributes->set($propertyName, $data);
}

Теперь, чтобы прояснить ситуацию, это работает и правильно вводит значение в параметры метода, поэтому в моем контроллере, если я добавлю что-то вроде этого:

/**
*@CheckRequest(name = "data")
*/
public function createAction(array $data){
}

Это работает, и параметр $ data заполняется.
Наконец, когда я объяснил все это, я теперь могу задать свой вопрос.
Это правильный способ сделать это, или есть какой-то «стандартизированный» способ ввода значения параметров через аннотации, и не могли бы вы привести пример? Я знаю что @ParamConverter аннотация делает такие вещи, но я не мог понять, как она связывает значение с параметром под капотом.
Заранее благодарю за ответы!

1

Решение

Я думаю, что вы можете сделать это немного более чисто, чем указывать параметр и передавать его каждой функции. Я хотел бы рассмотреть создание класса Controller, который расширяет базовый контроллер и имеет $data переменная в нем. Например:

Базовый контроллер

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class JsonRequestController extends Controller
{
/**
* @ var array
*/
private $data;

/**
* @return array
*/
public function getData()
{
return $this->data;
}

/**
* @param array $data
*/
public function setData(array $data)
{
$this->data= $data;
}
}

Тогда пусть ваш слушатель выполняет ваши проверки, только если вы находитесь в экземпляре JsonRequestController и аннотация установлена. Вы бы заполнили $data значение.

слушатель

public function onKernelController(FilterControllerEvent $event)
{
if (!is_array($controller = $event->getController())) {
return;
}

if (!$controller[0] instanceof JsonRequestController) {
return;
}

// ...

$controller[0]->setData(json_decode($content, true));

// ..
}

Ваш контроллер с аннотациями

/**
* @CheckRequest(name = "data")
*/
public function createAction()
{
// access via $this->getData()
}

Это упростит задачу, а затем, если вам потребуется расширить функциональность, вы сможете — например, иметь несколько различных переменных, для которых вы передаете параметры в аннотацию, или использовать protected вместо private и доступ к $data переменная напрямую и т. д.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector