Skip to content

Instantly share code, notes, and snippets.

@boekkooi
Last active December 23, 2020 02:49
Show Gist options
  • Save boekkooi/5600b3d43f694f26855d to your computer and use it in GitHub Desktop.
Save boekkooi/5600b3d43f694f26855d to your computer and use it in GitHub Desktop.
Using a custom property path for symfony forms set / get path

Sometimes you have a small little class like Rate.php and want to use it with a symfony form like:

$builder
    ->add('cost', MoneyType::class, [
        'currency' => 'EUR',
        'label' => 'Cost',
        'divisor' => 100,
    ]);

But S*** symfony forms expects a set<name> method. Let's change this behaviour by using a custom property accessor and overriding the path.

$builder
    ->setDataMapper(new PropertyPathMapper(
        new CustomPropertyAccessor([ 'cost' => 'changeCost' ])
    ));

All done.

<?php
use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\PropertyAccess\PropertyPath;
/**
* A property accessor that allows you to rewrite a property path for setters and getters.
*/
class CustomPropertyAccessor extends PropertyAccessor
{
/**
* @var array
*/
private $customSets;
/**
* @var array
*/
private $customGets;
/**
* @inheritDoc
*/
public function __construct(array $propertySets = [], array $propertyGets = [], $magicCall = false, $throwExceptionOnInvalidIndex = false)
{
parent::__construct($magicCall, $throwExceptionOnInvalidIndex);
$this->customSets = $propertySets;
$this->customGets = $propertyGets;
}
/**
* @inheritDoc
*/
public function getValue($objectOrArray, $propertyPath)
{
if (isset($this->customGets[(string)$propertyPath])) {
$propertyPath = new PropertyPath($this->customGets[(string)$propertyPath]);
}
return parent::getValue($objectOrArray, $propertyPath);
}
/**
* @inheritDoc
*/
public function setValue(&$objectOrArray, $propertyPath, $value)
{
if (isset($this->customSets[(string)$propertyPath])) {
$propertyPath = new PropertyPath($this->customSets[(string)$propertyPath]);
}
parent::setValue($objectOrArray, $propertyPath, $value);
}
}
<?php
class FaxRate
{
/**
* @var int
*/
protected $cost;
/**
* @return int
*/
public function getCost()
{
return $this->cost;
}
/**
* @param int $cost
*/
public function changeCost($cost)
{
$this->cost = $cost;
}
}
@freedmo
Copy link

freedmo commented Aug 29, 2019

@ostrolucky 'property_path' is not for this

Why not?

@reneroboter
Copy link

I guess the following part from the official documentation is also helpful for this topic.
https://symfony.com/doc/4.4/form/data_mappers.html

@lebrunthibault
Copy link

DataMappers are certainly more powerful but property path totally works for a simple use case ! thansk @ostrolucky

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment