EmbedMany в форме - PullRequest
       6

EmbedMany в форме

2 голосов
/ 15 апреля 2011

Я создал небольшой сайт Symfony2 (с Symfony PR11) с MongoDB в качестве БД. Я мог бы создать форму, которая использует обычный документ, но как мне использовать документ со встроенным документом?

вот документы:

/**
 * @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;
    }

}

Встроенный документ:

/**
 * @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;
    }

}

Как видите, $terminals содержит EmbedMany -Документ Вот форма:

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)));
    }
}

Используемый контроллер выглядит так:

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->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));
    }

Я мог видеть, что locationName получает введенные значения в форме, но EmbedMany -Array terminals все еще пуст. Что я не прав?

Спасибо за помощь: D

ОБНОВЛЕНИЕ:

Хорошо, нашли решение.

в public function addTerminals($dm) в LocationForm это должно выглядеть так:

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')));
}
  1. 'type' => 'timestamp' необходимо, потому что DateField создаст DateTime -объект, но в документе ожидается Int для timestamp.
  2. поле из массива terminals можно получить с помощью обычной точечной нотации.

Ответы [ 2 ]

0 голосов
/ 14 августа 2013

Symfony 2 на самом деле предоставляет вам инструмент для обработки встроенных документов в формах: он называется « тип поля коллекции » и позволяет встраивать другие типы форм (из других встроенных документов) в родительскую форму.

Он может быть настроен для разрешения / запрета добавления / удаления встроенных документов и на самом деле довольно мощный.

0 голосов
/ 18 августа 2012

Хорошо, найдено решение.

в public function addTerminals($dm) в LocationForm это должно выглядеть так:

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')));
}
  1. 'type' => 'timestamp' необходимо, потому что DateField создаст DateTime -объект, но в документе ожидается Int для timestamp.
  2. поле из массива terminals может быть доступно с помощью обычной точечной нотации.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...