In many cases you need to use full customer address form type or just some fields like country region or city , ok to know how to use firstly you should know that oro platform came with a bundle AddressBundle which manage global address structure for example address entity country entity and region entity , this bundle give you ability to add form address or select box of countries box and regions too and managing relation between country and regions by validation and events, as well as you can using the phone field or email field (collection too) ….
All other bundles in OroCommerce like customerBundle based on AddressBundle to manage addresses , So the big differences between general addresses and customer addresses that the second is typed which means for example billing address or shipping address .
The customer user form is inside vendor/oro/customer-portal/src/Oro/Bundle/CustomerBundle/Form/Type/CustomerTypedAddressType.php you can using inside your custom form or inject by from extension with builder , we have said the parent is:
use Oro\Bundle\AddressBundle\Form\Type\AddressType; /** * {@inheritdoc} */ public function getParent() { return AddressType::class; }
But this form type by default use a backend route to load the region related to each country on real time after country value get changed 'region_route' => 'oro_api_country_get_regions' inside vendor/oro/platform/src/Oro/Bundle/AddressBundle/Form/Type/AddressType.php:
/** * {@inheritdoc} */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults( 'data_class' => 'Oro\Bundle\AddressBundle\Entity\Address', 'csrf_token_id' => 'address', 'single_form' => true, 'region_route' => 'oro_api_country_get_regions' ) ); }
So if you’re using it for example in frontend by form extension you should be sure that you have use the correct 'region_route' => 'oro_api_frontend_country_get_regions':
/** * {@inheritdoc} */ $view->vars['region_route'] = 'oro_api_frontend_country_get_regions'; }
So now let’s create and example of an helper to save Data Address of your form : let’s create Address.php helper inside src/Ibnab/Bundle/CreateCustomerBundle/Helper/Address.php:
<?php namespace Oaklab\Bundle\CreateCustomerBundle\Helper; use Oro\Bundle\CustomerBundle\Entity\AbstractDefaultTypedAddress; use Doctrine\Common\Persistence\ManagerRegistry; use Oro\Bundle\CustomerBundle\Entity\CustomerAddress; use Doctrine\Common\Collections\ArrayCollection; class Address { /** @var ObjectRepository|EntityRepository */ protected $countryRepository; /** @var ObjectRepository|EntityRepository */ protected $regionRepository; /** @var ObjectRepository|EntityRepository */ protected $addressTypeRepository; /** @var ManagerRegistry */ private $registry; /** * @param ConfigManager $configProvider */ public function __construct(ManagerRegistry $registry) { $this->registry = $registry; } /** * @param $data * @return AbstractDefaultTypedAddress */ public function createAddress($data) { $this->initRepositories(); /** @var Country $country */ $country = $this->countryRepository->findOneBy(['iso2Code' => $data['country']]); if (!$country) { throw new \RuntimeException('Can\'t find country with ISO ' . $data['country']); } /** @var Region $region */ $region = $this->regionRepository->findOneBy(['country' => $country, 'code' => $data['state']]); if (!$region) { throw new \RuntimeException( ); } $types = []; foreach ($typesFromData as $type) { $types[] = $this->addressTypeRepository->find($type); } $defaultTypes = []; foreach ($defaultTypesFromData as $defaultType) { $defaultTypes[] = $this->addressTypeRepository->find($defaultType); } $address = $this->getNewAddressEntity(); $address->setTypes(new ArrayCollection($types)); $address->setDefaults(new ArrayCollection($defaultTypes)) ->setPrimary(true) ->setLabel('Primary address') ->setCountry($country) ->setStreet($data['street']) ->setCity($data['city']) ->setRegion($region) ->setPostalCode($data['zipCode']) ->setFirstName($data['firstName']) ->setLastName($data['lastName']); return $address; } protected function initRepositories() { $this->countryRepository = $this->registry ->getManagerForClass('OroAddressBundle:Country') ->getRepository('OroAddressBundle:Country'); $this->regionRepository = $this->registry ->getManagerForClass('OroAddressBundle:Region') ->getRepository('OroAddressBundle:Region'); $this->addressTypeRepository = $this->registry ->getManagerForClass('OroAddressBundle:AddressType') ->getRepository('OroAddressBundle:AddressType'); } public function getRegistry(){ return $this->registry; } /** * {@inheritdoc} */ protected function getNewAddressEntity() { return new CustomerAddress(); } }
the content of class is easy create a a new instance of class CustomerAddress and initialize repositories for country region and addressType entities , so and add an function createAddress($data) to use for persist data coming from from your form .
You can create a service to use inside your form type extension for example:
ibnab_create_customer.address_helper: class: Ibnab\Bundle\CreateCustomerBundle\Helper\Address public: true arguments: - "@doctrine"
Even you can use the country and region field separately and using to same technique to pass frontend api url and save .
Comments