2013-08-10 27 views
15

Po pierwsze, nie jestem pewien, czy to jest problem z Sonatą, czy Symfony2, po raz pierwszy pracuję z formularzami Sf2, aby edytować związek.Zatrzymaj SonataAdmin/Symfony2 przed utworzeniem pustych obiektów za pomocą wbudowanych administratorów sonata_type_admin

Oto problem:

mam dwie klasy, nazwijmy je starzy faworyci: Car i Wheel. Samochód ma opcjonalną relację jeden do jednego z Kołem (to na przykład, po prostu idź z nim ...). Skonfigurowałem SonataAdmin z klasą CarAdmin, która osadza WheelAdmin przy użyciu sonata_type_admin i próbuje utworzyć Samochód bez wprowadzania jakichkolwiek danych dla koła.

Jednak po przesłaniu (gdzieś w $ form-> bind()/$ form-> submit(), o ile mogę śledzić) Symfony i/lub Sonata tworzy koło i próbują je utrzymać (ze wszystkimi jego wartości jako null). Ponieważ Koło ma pewne nie-zerowe ograniczenia, powoduje to wyjątek DBALE, który narzeka, że ​​nie możesz WSTAWIĆ koła z zerowymi punktami odniesienia.

To jest niegrzeczne i chciałbym to przerwać. Jeśli nie wprowadzę żadnych danych dotyczących Koła, nie chcę, aby koło widmowe groziło moim kodem i bazą danych. Spodziewam się, że jeśli nie wprowadzę żadnych danych, nic nie zostanie wstawione/utrwalone, więc pozostawiam je w spokoju. Ale to nie jest to, co się dzieje ... wszelkie pomysły, jak to oswoić w coś sensownego?


Oto wersja długa, z bloków kodu i wszystko:

Definicje ORM pierwsze:

# MyNS\MyBundle\Resources\Config\Doctrine\Car.orm.yml 
MyNS\MyBundle\Entity\Car: 
    type: entity 
    repositoryClass: MyNS\MyBundle\Entity\Repositories\CarRepository 
    table: test_cars 
    id: 
    id: 
     type:      integer 
     generator:    { strategy: AUTO } 
    fields: 
    color: 
     type:      string 
     length:     50 
    owner: 
     type:      string 
     length:     50 
     nullable:     true 
    oneToOne: 
    leftFrontWheel: 
     targetEntity:    Wheel 
     cascade:     [ persist ] 
     joinColumn: 
     name:     leftFrontWheelId 
     referencedColumnName: id 


# MyNS\MyBundle\Resources\Config\Doctrine\Wheel.orm.yml 
MyNS\MyBundle\Entity\Wheel: 
    type: entity 
    repositoryClass: MyNS\MyBundle\Entity\Repositories\WheelRepository 
    table: test_wheels 
    id: 
    id: 
     type:      integer 
     generator:    { strategy: AUTO } 
    fields: 
    diameter: 
     type:      integer 
     length:     5 

Następnie klasach SonataAdmin:

namespace MyNS\MyBundle\Admin 

use ... 

class CarAdmin extends Admin 
{ 
    protected function configureFormFields(FormMapper $formMapper) 
    { 
     $formMapper 
      ->add('color',    null, array('required' => true)) 
      ->add('owner',    null, array('required' => false)) 
      ->add('leftFrontWheel',  'sonata_type_admin', array('delete' => false)) 
     ; 
    } 

    protected function configureListFields(ListMapper $listMapper) { ... } 
} 

i

namespace MyNS\MyBundle\Admin; 

use ... 

class WheelAdmin extends Admin 
{ 
    protected function configureFormFields(FormMapper $formMapper) 
    { 
     $formMapper 
      ->add('diameter', null, array('required' => false)) 
     ; 
    } 

    protected function configureListFields(ListMapper $listMapper) { ... } 
} 

i wreszcie admin.yml wpisów:

services: 
    sonata.admin.car: 
     class: MyNS\MyBundle\Admin\CarAdmin 
     tags: 
      - { name: sonata.admin, manager_type: orm, label: "Car" } 
     arguments: 
      - ~ 
      - MyNS\MyBundle\Entity\Car 
      - 'SonataAdminBundle:CRUD' 
     calls: 
      - [ setTranslationDomain, [MyNS\MyBundle]] 
    sonata.admin.wheel: 
     class: MyNS\MyBundle\Admin\WheelAdmin 
     tags: 
      - { name: sonata.admin, manager_type: orm, label: "Wheel" } 
     arguments: 
      - ~ 
      - MyNS\MyBundle\Entity\Wheel 
      - 'SonataAdminBundle:CRUD' 
     calls: 
      - [ setTranslationDomain, [MyNS\MyBundle]] 

Oczekiwany/wymagane zachowanie:

  • wyświetlić formularz z trzech dziedzin:

    • car.color (wymagane)
    • car.owner (opcjonalnie)
    • car.wheel.diameter (opcjonalnie)
  • jeśli car.wheel.diameter jest puste wtedy nie powinno być tworzone koła i test_cars.leftFrontWheelId powinny pozostać null w bazie

  • jeśli car.wheel.średnica jest wpisana wtedy koła powinny być tworzone i związany z Car (to wydaje się działać prawidłowo z istniejącym config)

na pytanie: Jak mogę dostać ten system zachowuje się jak powyżej?

+4

Myślę, że udało mi się stworzyć obejście tego problemu, ale musi być lepszy sposób! (W CarAdmin dodałem metody prePersist() i preUpdate(), które sprawdzają, czy koło nie ma swojej średnicy.Jeśli jest (tj. Jest nieważne) to '' $ car-> setLeftFrontWheel (null) '' usuwa relacje i przestaje próbować przetrwać puste koło.) – caponica

+0

Sonata jest podatna na błędy pojawiające się losowo, ale dość często. Spróbuj sprawdzić nową wersję, ponieważ opisane zachowanie nie występuje w mojej (starej) wersji. Powodzenia! – likeitlikeit

+0

Cóż, używam najnowszej wersji (dev-master) SonataAdmina, więc nie sądzę, żeby pojawiła się nowsza :) Jeszcze nie doświadczyłem z Symfony, żeby wiedzieć, czy to jest problem z Symfony, czy z Sonatą, kiedy wiem na pewno, że podniosę odpowiedni problem. – caponica

Odpowiedz

0

Może to być spowodowane brakującym 'required' => false, nie?

protected function configureFormFields(FormMapper $formMapper) { 
    $formMapper 
     ->add('color',    null, array('required' => true)) 
     ->add('owner',    null, array('required' => false)) 
     ->add('leftFrontWheel',  'sonata_type_admin', array('required' => false, 'delete' => false)) 
    ; 
} 
0

Zmień swoje pole Wheel formularz na coś takiego:

$formMapper 
    // ... 
    ->add('leftFrontWheel', 'sonata_type_admin', array(
     'delete' => false, 
     'by_reference => true, 
     'required' => false, 
    )) 
    // ... 

Zobacz by_referencedocumentation

Jeśli to nie wystarczy, należy użyć haka prePersist w swojej macierzystej grupy administratora i zarządzać które pole przechowywać . tj .:

// Fire on submit, before the object persisting 
public function prePersist($object) 
    if ($wheel = $object->getLeftFrontWheel()) { 
     if (!$wheel->getYourNonNullableField()) { 
      $object->setLefTFrontWheel(null); 
     } 
    } 
}