symfony - DataTransformer for IvoryGoogleMapBundle autocomplete (array) to an Address Entity -
i added autocomplete field registrationformtype (fosuserbundle) using ivorygooglemapbundle.
an user can have 1 address => onetoone relation
i created datatransformer transform autocomplete field (array) address entity following symfony documentation seems missed :(
i have following error: the required option "em" missing.
sw/userbundle/entity/user.php
class user extends baseuser { /** * @orm\onetoone(targetentity="sw\blogbundle\entity\address", cascade={"persist"}) * @orm\joincolumn(name="address_id", referencedcolumnname="id") */ private $address; /** * set address * * @param \sw\blogtbundle\entity\address $address * @return user */ public function setaddress(\sw\blogbundle\entity\address $address = null) { $this->address = $address; return $this; } /** * address * * @return \sw\blogbundle\entity\address */ public function getaddress() { return $this->address; }
sw/blogbundle/entity/address.php
class address { /** * @orm\id * @orm\column(type="integer") * @orm\generatedvalue(strategy="auto") */ protected $id; /** * @orm\column(type="string", length=10) */ private $zipcode; /** * @orm\column(type="string", length=45) */ private $city; /** * @orm\column(type="string", length=45) */ private $country;
sw/blogbundle/form/autocompletefromtype.php
use ivory\googlemap\places\autocompletetype; use ivory\googlemap\places\autocompletecomponentrestriction; class mapformtype extends abstracttype { public function buildform(formbuilderinterface $builder, array $options) { $builder->add('ville','places_autocomplete', array( 'prefix' => 'js_prefix_', 'types' => array(autocompletetype::cities), 'async' => false, 'language' => 'fr', 'component_restrictions' => array( autocompletecomponentrestriction::country => 'fr'), )); } public function getname() { return 'sw_blog_autocomplete'; } }
sw/userbundle/form/type/registrationformtype.php
use sw\blogbundle\form\autocompleteformtype; use sw\blogbundle\form\datatransformer\autocompletetoaddresstransformer; class registrationformtype extends abstracttype { protected $em; public function __construct(entitymanager $em) { $this->em = $em; } public function buildform(formbuilderinterface $builder, array $options) { $entitymanager = $options['em']; $transformer = new autocompletetoaddresstransformer($entitymanager); parent::buildform($builder, $options); $builder->add('username', 'text', array('label' => 'pseudo :', 'max_length' => 10)); ......... $builder->add($builder->create('address', new mapformtype(), array('label' => 'adresse :','required' => true))->addmodeltransformer($transformer)); } public function setdefaultoptions(optionsresolverinterface $resolver) { $resolver ->setdefaults(array( 'data_class' => 'sw\userbundle\entity\user', )) ->setrequired(array( 'em', )) ->setallowedtypes(array( 'em' => 'doctrine\common\persistence\objectmanager', )); // ... } public function getname() { return 'sw_user_registration'; } }
sw/blogbundle/form/datatransformer/autocompletetoaddresstransformer.php
use sw\blogbundle\entity\address; use ivory\googlemap\services\geocoding\geocoder geocoderservice; class autocompletetoaddresstransformer implements datatransformerinterface { /** * @var objectmanager */ private $om; /** * @param objectmanager $om */ public function __construct(objectmanager $om) { $this->om = $om; } /** * transforms array object (address). * * @param array|null $autocomplete * @return address */ public function transform($autocomplete) { if (null === $autocomplete) { return ""; } $geocoder = new geocoderservice(); try { $result = $geocoder->geocode($autocomplete); var_export($result); } catch (exception $e) { echo $e->getmessage(); } $address = new address(); $address->setcity($result->getcity()); $address->setcoutry($result->getcoutry()); $address->setzipcode($result->getzipcode()); return $address; } /** * transforms object (address) array. * * @param address $address * * @return autocomplete|null * * @throws transformationfailedexception if array not found. */ public function reversetransform($address) { if (!$address) { return null; } $autocomplete = $address->getcity. ' , ' .$address->getcountry; return $autocomplete; } }
sw/userbundle/controller/registrationcontroller.php
<?php namespace sw\userbundle\controller; use symfony\component\httpfoundation\redirectresponse; use fos\userbundle\controller\registrationcontroller basecontroller; use symfony\component\httpfoundation\request; use fos\userbundle\fosuserevents; use fos\userbundle\event\userevent; use fos\userbundle\event\formevent; use fos\userbundle\event\filteruserresponseevent; use sw\userbundle\form\type\registrationformtype; class registrationcontroller extends basecontroller { public function registeraction(request $request) { /** @var $formfactory \fos\userbundle\form\factory\factoryinterface */ $formfactory = $this->container->get('fos_user.registration.form.factory'); /** @var $usermanager \fos\userbundle\model\usermanagerinterface */ $usermanager = $this->container->get('fos_user.user_manager'); /** @var $dispatcher \symfony\component\eventdispatcher\eventdispatcherinterface */ $dispatcher = $this->container->get('event_dispatcher'); $user = $usermanager->createuser(); $user->setenabled(true); $dispatcher->dispatch(fosuserevents::registration_initialize, new userevent($user, $request)); $form = $formfactory->createform(new registrationformtype(), $user, array( 'em' => $this->container->get('doctrine')->getmanager(), )); $form->setdata($user); if ('post' === $request->getmethod()) { $form->bind($request); if ($form->isvalid()) { $form->bind($request); $event = new formevent($form, $request); $dispatcher->dispatch(fosuserevents::registration_success, $event); $usermanager->updateuser($user); if (null === $response = $event->getresponse()) { $url = $this->container->get('router')->generate('fos_user_registration_confirmed'); $response = new redirectresponse($url); } $dispatcher->dispatch(fosuserevents::registration_completed, new filteruserresponseevent($user, $request, $response)); return $response; } } return $this->container->get('templating')->renderresponse('fosuserbundle:registration:register.html.'.$this->getengine(), array( 'form' => $form->createview(), )); } }
i don't know if right , easiest way save autocomplete field address entity...
thank help
i see 2 issues in code. first 1 (not important), should rely on di component (container) create form type when needs dependency. see http://symfony.com/doc/current/cookbook/form/create_custom_field_type.html#creating-your-field-type-as-a-service more details.
this way, able make dependency explicit (your object manager can directly pass constructor of form type instead of passing form option).
the second issue geocoder not created. here, create geocoder without provider. see comment more details https://github.com/egeloen/ivory-google-map/issues/32#issuecomment-20461264
then, awre if refactor form type service, geocoder provided bundle configured provider. injecting ivory_google_map.geocoder
service enough.
Comments
Post a Comment