Is is a very simple DataMapper that will create a instance of a class based on the form input using the class constructor. This works great for values objects or commands.
namespace Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints;
use ValueObject\Address;
use Acme\Symfony\Form\DataMapper\ConstructorMapper;
class AddressFormType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->add('street', 'text', [
'label' => 'form.street',
'translation_domain' => 'Address',
'constraints' => [
new Constraints\NotBlank(),
new Constraints\Length(['min' => 2, 'max' => 255])
]
])
->add('zipCode', 'text', [
'label' => 'form.zip_code',
'translation_domain' => 'Address',
'constraints' => [
new Constraints\NotBlank(),
new Constraints\Length(['min' => 2, 'max' => 50])
]
])
->add('city', 'text', [
'label' => 'form.city',
'translation_domain' => 'Address',
'constraints' => [
new Constraints\NotBlank(),
new Constraints\Length(['min' => 2, 'max' => 255])
]
])
->add('region', 'text', [
'required' => false,
'label' => 'form.region',
'translation_domain' => 'Address',
'constraints' => [
new Constraints\Length(['max' => 255])
]
])
->add('country', 'country', [
'label' => 'form.country',
'translation_domain' => 'Address',
'choice_translation_domain' => false,
'empty_value' => 'Choose an option',
'constraints' => [
new Constraints\NotBlank(),
new Constraints\Country(),
new Constraints\Length(['min' => 2, 'max' => 4])
]
])
->setDataMapper(new ConstructorMapper(Address::class));
}
/**
* @inheritdoc
*/
public function getName()
{
return 'address';
}
}
namespace ValueObject;
use Symfony\Component\Intl\Intl;
use Assert;
use ValueObject\ValueObject;
/**
* Address value object
*/
final class Address implements ValueObject
{
/**
* @var string
*/
private $street;
/**
* @var string
*/
private $zipCode;
/**
* @var string
*/
private $city;
/**
* @var string
*/
private $region;
/**
* @var string
*/
private $country;
/**
* @param string $street
* @param string $zipCode
* @param string|null $region
* @param string $city
* @param string $country
*/
public function __construct($street, $zipCode, $region = null, $city, $country)
{
Assert\lazy()
->that($street, 'street')->string()->minLength(2)->maxLength(255)
->that($zipCode, 'zipCode')->string()->minLength(2)->maxLength(50)
->that($city, 'city')->string()->minLength(2)->maxLength(255)
->that($region, 'region')->nullOr()->string()->maxLength(255)
->that($country, 'country')->string()->maxLength(2, 4)->inArray(array_keys(Intl::getRegionBundle()->getCountryNames()))
->verifyNow();
$this->city = $city;
$this->country = $country;
$this->region = $region;
$this->street = $street;
$this->zipCode = $zipCode;
}
/**
* @return string
*/
public function getStreet()
{
return $this->street;
}
/**
* @return string
*/
public function getZipCode()
{
return $this->zipCode;
}
/**
* @return string
*/
public function getCity()
{
return $this->city;
}
/**
* @return string
*/
public function getRegion()
{
return $this->region;
}
/**
* @return string
*/
public function getCountry()
{
return $this->country;
}
/**
* @param string|null $locale
* @return string
*/
public function getCountryName($locale = null)
{
return Intl::getRegionBundle()->getCountryName($this->country, $locale);
}
/**
* @inheritdoc
*/
public function equals($object)
{
return
$object instanceof self &&
$this->street === $object->street &&
$this->zipCode === $object->zipCode &&
$this->city === $object->city &&
$this->region === $object->region &&
$this->country === $object->country;
}
}