控制器必须返回响应(给定Object(AppBundle \\ Entity \\ User))

时间:2018-07-12 15:16:19

标签: rest api symfony return patch

我收到此消息“控制器必须返回响应(给定对象(App Bundle \ Entity \ User))。”当我尝试用邮递员修补用户密码或用户名时...请帮助

但是更改用户名或密码...!我不知道为什么,但是那行得通,只是消息不好...

我的用户控制器:

use AppBundle\Entity\EntityMerger;
use AppBundle\Entity\User;
use AppBundle\Exception\ResourceValidationException;
use Lexik\Bundle\JWTAuthenticationBundle\Encoder\JWTEncoderInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use FOS\RestBundle\Controller\Annotations as Rest;

/**
* @Security("is_anonymous() or is_authenticated()")
*/
class UsersController extends AbstractController
{
 /**
 * @var UserPasswordEncoderInterface
 */
private $passwordEncoder;

/**
 * @var JWTEncoderInterface
 */
private $jwtEncoder;

/**
 * @var EntityMerger
 */
private $entityMerger;

/**
 * UsersController constructor.
 * @param UserPasswordEncoderInterface $passwordEncoder
 * @param JWTEncoderInterface $jwtEncoder
 * @param EntityMerger $entityMerger
 */
public function __construct(UserPasswordEncoderInterface $passwordEncoder, JWTEncoderInterface $jwtEncoder, EntityMerger $entityMerger)
{
    $this->passwordEncoder = $passwordEncoder;
    $this->jwtEncoder = $jwtEncoder;
    $this->entityMerger = $entityMerger;
}

/**
 * @Rest\View()
 * @Security("is_granted('show', theUser)", message="Access denied")
 */
public function getUserAction(?User $theUser)
{
    if (null === $theUser) {
        throw new NotFoundHttpException();
    }

    return $theUser;
}

/**
 *
 * @Rest\Post(
 *     path = "/users",
 *     name = "users_add"
 * )
 * @Rest\View(StatusCode=201)
 * @ParamConverter(
 *     "user",
 *     converter="fos_rest.request_body",
 *     options={"deserializationContent"={"groups"={"Deserialize"}}}
 * )
 */
public function postUserAction(User $user, 
ConstraintViolationListInterface $violations)
{
    if (count($violations) > 0) {
        $message = 'The user is not valid: ';
        foreach ($violations as $violation) {
            $message .= sprintf(
                "Field %s: %s ",
                $violation->getPropertyPath(),
                $violation->getMessage()
            );
        }

        throw new ResourceValidationException($message);
    }

    $this->encodePassword($user);
    $user->setRoles([User::ROLE_USER]);

    $this->persistUser($user);

    return $user;
}

/**
 * @Rest\Patch(
 *     path = "/users/{theUser}",
 *     name= "patch_user"
 * )
 * @ParamConverter(
 *     "modifiedUser",
 *     converter="fos_rest.request_body",
 *     options={
 *      "validator"={"groups"={"Patch"}},
 *      "deserializationContext"={"groups"={"Deserialize"}}
 *     }
 * )
 * @Security("is_granted('edit', theUser)", message="Access Denied")
 */
public function patchUserAction(?User $theUser, User $modifiedUser, 
ConstraintViolationListInterface $violations)
{
    if (null === $theUser) {
        throw new NotFoundHttpException();
    }

    if (empty($modifiedUser->getPassword())) {
        $modifiedUser->setPassword(null);
    }

    if (count($violations) > 0) {
        $message = 'The user is not valid: ';
        foreach ($violations as $violation) {
            $message .= sprintf(
                "Field %s: %s",
                $violation->getPropertyPath(),
                $violation->getMessage()
            );
        }
        throw new ResourceValidationException($message);
    }

    $this->entityMerger->merge($theUser, $modifiedUser);

    $this->encodePassword($theUser);
    $this->persistUser($theUser);

    return $theUser;
}

/**
 * @param User $user
 */
protected function encodePassword(User $user): void
{
    $user->setPassword(
        $this->passwordEncoder->encodePassword(
            $user,
            $user->getPassword()
        )
    );
}

/**
 * @param User $user
 */
protected function persistUser(User $user): void
{
    $em = $this->getDoctrine()->getManager();
    $em->persist($user);
    $em->flush();
}
}

我的EntityMerger:

namespace AppBundle\Entity;


use Doctrine\Common\Annotations\Reader as AnnotationReader;
use Doctrine\ORM\Mapping\Id;

class EntityMerger
    {
/**
* @var AnnotationReader
*/
private $annotationReader;

public function __construct(AnnotationReader $annotationReader)
{
    $this->annotationReader = $annotationReader;
}

/**
 * @param $entity
 * @param $changes
 */
public function merge($entity, $changes)
{
    $entityClassName = get_class($entity);

    if (false === $entityClassName) {
        throw new \InvalidArgumentException('$entity is not a class');
    }

    $changesClassName = get_class($changes);

    if (false == $changesClassName) {
        throw new \InvalidArgumentException('$entity is not a class');
    }

    if (!is_a($changes, $entityClassName)) {
        throw new \InvalidArgumentException("Cannot merge object of class $changesClassName with object of class $entityClassName");
    }

    $entityReflection = new \ReflectionObject($entity);
    $changesReflection = new \ReflectionObject($changes);

    foreach ($changesReflection->getProperties() as $changedProperty) {
        $changedProperty->setAccessible(true);
        $changedPropertyValue = $changedProperty->getValue($changes);

        if(null === $changedPropertyValue) {
            continue;
        }

        if (!$entityReflection->hasProperty($changedProperty->getName())) {
            continue;
        }

        $entityProperty = $entityReflection->getProperty($changedProperty->getName());
        $annotation = $this->annotationReader->getPropertyAnnotation($entityProperty, Id::class);

        if (null !== $annotation) {
            continue;
        }

        $entityProperty->setAccessible(true);
        $entityProperty->setValue($entity, $changedPropertyValue);
    }
}
}

1 个答案:

答案 0 :(得分:0)

该消息正确指出您没有返回响应对象。

manualThe only requirement for a controller is to return a Response object

如果要返回对象,则可以返回JSON: return $this->json(['user' => $theUser]);

这只是代码中的一个猜测,因为您的问题并未说明您要返回的内容。