W swoim module poprzez UserDataSubscriber rozszerzam istniejący formularz edycji użytkownika (pracownika) o listę checkboxów z województwami.
Utworzyłem encję województwo:
/** * @ORM\Entity() * @ORM\Table(name="crm_main_province") */ class Province { /** * @ORM\Id * @ORM\Column(type="string", length=2) * * @var string $id */ protected $id; /** * @ORM\Column(type="string", length=255) * * @Assert\NotBlank() */ protected $name; /** * @ORM\Column(type="text", nullable=true) */ protected $description; /** * Constructor */ public function __construct() { $this->user = new \Doctrine\Common\Collections\ArrayCollection(); } /** * Set id * * @param string $id * @return Province */ public function setId($id) { $this->id = $id; return $this; } /** * Get id * * @return string */ public function getId() { return $this->id; } /** * Set name * * @param string $name * @return Province */ public function setName($name) { $this->name = $name; return $this; } /** * Get name * * @return string */ public function getName() { return $this->name; } /** * Set description * * @param string $description * @return Province */ public function setDescription($description) { $this->description = $description; return $this; } /** * Get description * * @return string */ public function getDescription() { return $this->description; } }
oraz encję odpowiedzialną za utworzenie nowej tabeli (scalającej) w której chcę trzymać wiersze z ID-kiem użytkownika i w kolejnej kolumnie zserializowaną tablicę kolekcji zawierającą listę województw:
/** * @ORM\Entity() * @ORM\Table(name="crm_main_employeeprovince") */ class EmployeeProvince { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") * * @var integer $id */ protected $id; /** * @ORM\OneToOne(targetEntity="\MainBundle\Entity\User") * @ORM\JoinColumn(onDelete="SET NULL") */ protected $user; /** * @ORM\Column(name="provinces", type="array", nullable=false) */ protected $provinces; public function __construct() { $this->provinces = new ArrayCollection(); } /** * Get id * * @return integer */ public function getId() { return $this->id; } public function addProvinces($province) { $this->provinces->add($province); return $this; } /** * Set provinces * * @param array $provinces * @return EmployeeProvince */ public function setProvinces($provinces) { $this->provinces = $provinces; return $this; } /** * Get provinces * * @return array */ public function getProvinces() { return $this->provinces; } /** * Set user * * @param \MainBundle\Entity\User $user * @return EmployeeProvince */ public function setUser(\MainBundle\Entity\User $user = null) { $this->user = $user; return $this; } /** * Get user * * @return \MainBundle\Entity\User */ public function getUser() { return $this->user; } }
Lista checkboxów zapisuje się poprawnie tylko przy pierwszej edycji pracownika, w momencie kiedy już jakieś dane znajdują się w kolumnie "provinces" encji "EmployeeProvince" kolejne się nie nadpisują, nie leci żaden błąd.
Poniżej funkcja z UserDataSubscriber odpowiedzialna za przygotowanie formularza i dodanie checkboxów:
public function onEmployeeEditFormBuild(FormBuilderEvent $event) { /** * Remember to always check if user is granted! */ if (!$this->context->isGranted('crm_employee_edit')) { return; } $builder = $event->getBuilder(); $options = $event->getOptions(); $dynamicData = $builder->getData(); $user = $dynamicData->getSubject(); // Default object $employeeProvince = new \MainBundle\Entity\EmployeeProvince; // Check if employee has id - if so it means that it's edit. if ($user->getId()) { $employeeProvince = $this->doctrine->getRepository('MainBundle:EmployeeProvince')->findOneByUser($user); } $dynamicData->addExtra('employee_province', $employeeProvince); 'label' => 'Województwa przypisane do pracownika', )); }
oraz metoda subscribera po wysłaniu POSTa:
public function onEmployeeEditFormPost(GenericEvent $event) { /** * Remember to always check if user is granted! */ if (!$this->context->isGranted('crm_employee_edit')) { return; } $employeeProvince = $event->getArgument('employee_province'); $employeeProvince->setUser($event->getSubject()); $em = $this->doctrine->getManager(); $em->persist($employeeProvince); }
Załączam jeszcze definicję dodatkowego pola formularza o którym mówimy (lista checkboxów z województwami):
class EmployeeProvinceType extends AbstractType { { 'class' => 'MainBundle:Province', 'query_builder' => function($repository) { return $repository->createQueryBuilder('p')->orderBy('p.id', 'ASC'); }, 'property' => 'name', 'label' => 'Województwa', 'multiple' => true, 'expanded' => true, 'by_reference' => true, )); } public function setDefaultOptions(OptionsResolverInterface $resolver) { 'data_class' => 'MainBundle\Entity\EmployeeProvince', 'edit' => false, )); } public function getName() { return 'employee_provinces_list'; } }
Druga sprawa - jeśli jakiekolwiek województwo zostało zapisane to żaden checkbox nie jest widoczny jako zaznaczony. - w czym może być problem?
Czy w ogóle pomysł żeby listę województw trzymać jako ArrayCollection na pewno jest trafiony? Tak naprawdę jest to metoda sugerowana przez dokumentację: http://symfony.com/doc/current/cookbook/fo...ollections.html. Nie mam możliwości w encji "User" (znajduje sie w oddzielnym module, nie mogę jej edytować) zdefiniować relację ManyToMany tak jak Bóg przykazał.
Będę wdzięczny za konstruktywną pomoc!!!