通常,在具有多个客户的公共API上 - 所有实体应属于特定实体(即公司,用户等) - 该实体的所有者。
实体资源:
/**
* @ORM\Entity()
* @ORM\Table(name="resource", uniqueConstraints={
* @ORM\UniqueConstraint(columns={"customer_id", "name"})
* })
* @UniqueEntity(fields={"customer", "name"}, groups={"save"})
*
* @JMS\ExclusionPolicy("all")
*/
class Resource
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*
* @JMS\Expose()
* @JMS\Groups({"save_response"})
* @JMS\Type(name="integer")
*/
private $id;
/**
* @var Customer
*
* @ORM\ManyToOne(targetEntity="Customer", inversedBy="articles", cascade={"persist"})
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*
* @JMS\Type("AppBundle\Entity\Customer")
*/
private $customer;
...
}
实体客户:
/**
* @ORM\Entity()
* @ORM\Table(name="customer")
*
* @JMS\ExclusionPolicy("all")
*/
class Customer
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @var ArrayCollection<Resource>
*
* @ORM\OneToMany(targetEntity="Resource", mappedBy="customer", cascade={"persist", "remove"})
*
* @JMS\Type("ArrayCollection<AppBundle\Entity\Resource>"))
*/
private $resources;
..
}
控制器:
class VariableController extends FOSRestController
{
/**
* @Rest\Post(path="", name="resource_add")
* @ParamConverter("resource", converter="fos_rest.request_body", options={"validator"={"groups"="save"}, "deserializationContext"={"groups"={"save"}}})
* @param Resource $resource
* @param ConstraintViolationList $validationErrors
* @return View
*/
public function addAction(Resource $resource ConstraintViolationList $validationErrors)
{
if (count($validationErrors)) { //Doesn't check for EntityUnique constraint - because its empty on request
return $this->view($validationErrors, Response::HTTP_BAD_REQUEST);
}
$resource->setCustomer($this->getUser()->getCustomer()); //This should be done automatically
$em = $this->getDoctrine()->getManager();
$em->persist($resource);
$em->flush();
return $this->view($resource, 200);
}
}
Resource
&#39; s @UniqueEntity(fields={"customer", "name"}, groups={"save"})
未被使用,只是因为客户关系为空。
有没有办法使用@ParamConverter在Resource
上设置登录用户(或他的某个关系)?
请指教, 谢谢!
答案 0 :(得分:1)
活动订阅者,请收听serializer.post_deserialize
。
company.aware.subscriber:
class: AppBundle\Request\API\CompanyAwareSubscriber
tags:
- { name: jms_serializer.event_subscriber }
namespace AppBundle\Request\API;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
/**
*
*/
class CompanyAwareSubscriber implements EventSubscriberInterface
{
/**
* @var TokenStorage
*/
protected $tokenStorage;
/**
* @param $tokenStorage TokenStorage
*/
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
/**
* @inheritdoc
*/
static public function getSubscribedEvents()
{
return array(
array('event' => 'serializer.post_deserialize', 'method' => 'onPostDeserialize'),
);
}
/**
* Manipulate Entity
*
* @param ObjectEvent $event
* @return ObjectEvent
*/
public function onPostDeserialize(ObjectEvent $event)
{
/**
* CompanyAware must be set:
* @ParamConverter("variable", converter="fos_rest.request_body", "deserializationContext"={"CompanyAware"=true}}})
*/
if(!$event->getContext()->attributes->containsKey('CompanyAware') ||
!$event->getContext()->attributes->get('CompanyAware')->get()) {
return $event;
}
//Check that a user is logged in
if(!$this->tokenStorage->getToken() || !($user = $this->tokenStorage->getToken()->getUser())) {
return $event;
}
if(!($user instanceof CompanyAwareInterface)) {
return $event;
}
//Check that entity is not set with a company already
/** @var CompanyAwareInterface $object */
$object = $event->getObject();
if(!($object instanceof CompanyAwareInterface) || $object->getCompany()) {
return $event;
}
$object->setCompany($user->getCompany());
return new ObjectEvent($event->getContext(), $object, $event->getType());
}
}
namespace AppBundle\Request\API;
use AppBundle\Entity\Company;
interface CompanyAwareInterface {
public function setCompany(Company $company);
public function getCompany();
}
要使用CompanyAware
侦听器,您需要添加以下内容:
让您的User
实体实施CompanyAwareInterface:
class User implements UserInterface, CompanyAwareInterface
接下来,对您希望此侦听器与之交互的每个实体执行相同的操作:
class Resource implements CompanyAwareInterface
最后,将CompanyAware
添加到@ParamConverter
:
@ParamConverter("resource", converter="fos_rest.request_body", options={"deserializationContext"={"CompanyAware"=false}})
是的,我可以使结构更抽象,更易于使用。但目前它并不值得。
祝你好运!