I'm developing a RESTful web service using Symfony with FOSRestBundle
From the front end I have a form that creates fields and sends to the server with the follow format:
{"targets":[1,3],"title":"This is a title","price":1200000,"description":"This is a description"}
The key targets
has TargetField
ids. With the below code I get a response with status code 500 saying that foreach argument is invalid (See FieldType->buildForm()
)
Field
/**
* @ORM\Table(name="field")
* @ORM\Entity
*/
class Field extends Property {
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="FieldTarget")
* @ORM\JoinTable(name="relFieldTarget",
* joinColumns={@ORM\JoinColumn(name="fieldId", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="fieldTargetId", referencedColumnName="id")}
* )
* */
private $targets;
public function __construct() {
$this->targets = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getTargets() {
return $this->targets;
}
}
FieldTarget
/**
* @ORM\Table(name="fieldTarget")
* @ORM\Entity
*/
class FieldTarget
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
* @ORM\Column(name="title", type="string")
**/
private $title
}
FieldType
class FieldType extends PropertyType {
private $manager;
function __construct(ObjectManager $manager){
$this->manager = $manager;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
$builder
->add('targets');
$builder
->get('targets')
->addModelTransformer(new CallbackTransformer(
function($fieldTargetIds) { // $fieldTargetIds is empty. WHY!?
$fieldTargetRepo = $this->manager->getRepository('FooBundle:FieldTarget');
foreach($fieldTargetIds as $id){
$fieldTarget[] = $fieldTargetRepo->find($id);
}
return $fieldTargets; // Here I'm tried hardcoding array($fieldTargetRepo->find(1)) and the field is created but is not related with the fieldTarget 1
},
function() {
}));
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Cboujon\PropertyBundle\Entity\Field'
));
}
}
FieldController
/**
* Create a Field entity.
*
* @View(statusCode=201, serializerEnableMaxDepthChecks=true)
*
* @param Request $request
*
* @return Response
*
*/
public function postAction(Request $request) {
$entity = new Field();
$form = $this->createForm(new FieldType($this->getDoctrine()->getManager()), $entity, array("method" => $request->getMethod()));
$this->removeExtraFields($request, $form);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $entity;
}
return FOSView::create(array('errors' => $form->getErrors()), Codes::HTTP_INTERNAL_SERVER_ERROR);
}
You are putting the code in the wrong function. The first function in a callback transformer transforms from the model into the view and the second transforms from the view into the model. In this case you are trying to add code for the second operation. Change your code to :
->addModelTransformer(new CallbackTransformer(
function($fieldTargets) {
//TODO: code to transform from the model into the view
},
function($fieldTargetIds) {
$fieldTargetRepo = $this->manager->getRepository('FooBundle:FieldTarget');
foreach($fieldTargetIds as $id){
$fieldTarget[] = $fieldTargetRepo->find($id);
}
return $fieldTargets;
}));