I've created a small Symfony2-Website (with Symfony PR11) with MongoDB as DB. I could create a form, that use a normal document, but how do I use a document with an embeddedDocument?
here are the documents:
/**
* @mongodb:Document(collection="location")
*/
class Location
{
/**
* @mongodb:Id
*/
protected $id;
/**
* @mongodb:String
*/
protected $locationName;
/**
* @mongodb:EmbedMany(targetDocument="LocationTerminal")
*/
protected $terminals = array();
// Setter
public function setTerminals(LocationTerminal $terminal)
{
array_push($this->terminals, $terminal);
}
public function setLocationName($locationName)
{
$this->locationName = $locationName;
}
// Getter
public function getId()
{
return $this->$id;
}
public function getLocationName()
{
return $this->locationName;
}
public function getTerminals()
{
return $this->terminals;
}
}
The EmbeddedDocument:
/**
* @mongodb:EmbeddedDocument
*/
class LocationTerminal
{
/**
* @mongodb:String
*/
protected $terminalName;
/**
* @mongodb:Int
*/
protected $since;
/**
* @mongodb:Int
*/
protected $to;
// Setter
public function setTerminalName($terminalName)
{
$this->terminalName = $terminalName;
}
public function setSince($since)
{
$this->since = $since;
}
public function setTo($to)
{
$this->to = $to;
}
// Getter
public function getTerminalName()
{
return $this->terminalName;
}
public function getSince()
{
return $this->since;
}
public function getTo()
{
return $this->to;
}
}
As you can see $terminals
holds an EmbedMany
-Document
Here's the form:
class LocationForm extends Form
{
public function configure()
{
$this->add(new TextField('locationName', array('max_length' => 255, 'required' => true)));
}
public function addTerminals($dm)
{
$this->add(new ChoiceField('terminals.terminalName', array('choices' => $dm)));
$this->add(new DateField('terminals.since', array('required' => true)));
$this->add(new DateField('terminals.to', array('required' => false)));
}
}
The used Controller looks like this:
class LocationController extends Controller
{
protected $location;
protected $locationTerminal;
protected function getDm()
{
return $this->get('doctrine.odm.mongodb.document_manager');
}
protected function getLocation($name = null)
{
if ($name != null)
{
$dm = $this->getDm();
$this-&开发者_StackOverflow中文版gt;location = $dm->getRepository('RalfBundle:Location')->findOneBy(array('locationName' => $name));
if (! $this->location)
{
$this->location = new Location();
$this->locationTerminal = new LocationTerminal();
$this->location->setLocation($name);
$this->location->setTerminals($this->locationTerminal);
}
}
else
{
$this->location = new Location();
$this->locationTerminal = new LocationTerminal();
$this->location->setTerminals($this->locationTerminal);
$this->locationTerminal->setSince(0);
$this->locationTerminal->setTerminalName("");
$this->locationTerminal->setTo(0);
}
}
protected function getForm()
{
$form = LocationForm::create($this->get('form.context'), 'location');
$dm = $this->getDm();
$form->addTerminals($dm->getRepository('RalfBundle:Terminal')->findAll()->toArray());
return $form;
}
//... some Actions
public function createAction()
{
$this->getLocation();
$form = $this->getForm();
$form->bind($this->get('request'), $this->location);
if ($form->isValid())
{
$dm = $this->getDm();
$dm->persist($this->location);
$dm->flush();
return $this->redirect($this->generateUrl('Location'));
}
return $this->render('RalfBundle:Ralf:location_create.html.twig', array('form' => $form));
}
I could see, that locationName
recieve the entered values in the form, but the EmbedMany
-Array terminals
is still empty.
What did I wrong?
Thanks for helping :D
UPDATED:
Ok, found a solution.
in public function addTerminals($dm)
in LocationForm
it should look like this:
public function addTerminals($dm)
{
$this->add(new ChoiceField('terminals.0.terminalName', array('choices' => $dm)));
$this->add(new DateField('terminals.0.since', array('required' => true, 'type'=> 'timestamp')));
$this->add(new DateField('terminals.0.to', array('required' => false, 'type' => 'timestamp')));
}
'type' => 'timestamp'
is necessary, 'causeDateField
will create anDateTime
-Object, but the document expected anInt
fortimestamp
.- a field from the
terminals
-array could be accessed by normal dot-notation.
Ok, found a solution.
in public function addTerminals($dm)
in LocationForm
it should look like this:
public function addTerminals($dm)
{
$this->add(new ChoiceField('terminals.0.terminalName', array('choices' => $dm)));
$this->add(new DateField('terminals.0.since', array('required' => true, 'type'=> 'timestamp')));
$this->add(new DateField('terminals.0.to', array('required' => false, 'type' => 'timestamp')));
}
'type' => 'timestamp'
is necessary, 'causeDateField
will create anDateTime
-Object, but the document expected anInt
fortimestamp
.- a field from the
terminals
-array could be accessed by normal dot-notation.
Symfony 2 actually gives you a tool to handle embedded documents in forms: It's called "collection field type" and it enables you to embed other formtypes (from other embedded documents) in a parent form.
It can be configured to allow/forbid addition/deletion of embedded documents and is actually quite powerful.
精彩评论