The cookbook suggests to use DataTransformer to strip_tags from input.
Isn't that violation of _"Transforms a value between different representations"_?
I mean, when u strip tags, it's not that representation of data changes – it's the data itself that gets changed. Stripping tags is a losing data procedure.
A cleaner way would be to use form event listener to change the data.
The example is almost right to use DataTransformer to change '<br>'s to "\n" and vice versa – almost, because the input could have both '<br>'s and "\n" – the original information, which should be where, would be lost as well.
You are right. Stripping some information means that the transformer no longer is bijective. Can we come up with a better example use case?
The use case of @dmaicher described in https://github.com/symfony/symfony/issues/18173 might fit. What do you think ?
@HeahDude I think it should be something simpler, more obvious.
How about base64_encode/base64_decode?
Another proposal: implode() / explode() to turn strings into/from arrays.
I don't use transformers myself for now, but I thought that giving a doctrine ArrayCollection to a field and expecting the form to treat it as an array and give you back a collection might help others (new comers?) dealing with entities in any form type.
That does not seem that complicated to me :)
In any case I think the example should match real use cases.
@MacDada @javiereguiluz Have you an example where base64 encoding/decoding or array implode/explode might be useful? I guess there must be some :)
What about simple prefix or suffix used in model data but not in an editable form representation:
class PrefixDataTransformer implements DataTransformerInterface
{
private $prefix;
public function __construct($prefix = null)
{
$this->prefix = $prefix;
}
public function transform($value)
{
if (null === $value || '' === $value) {
return;
}
if (0 === strpos($value, $this->prefix) {
return substr($value, strlen($this->prefix));
}
return $value
}
public function reverseTransform($value)
{
if (null === $value || '' === $value) {
return;
}
if (0 !== strpos($value, $this->prefix) {
return $this->prefix.$value;
}
return $value
}
?
@HeahDude I used the implode/explode example myself in the past because I had a tags property of type array in one Doctrine entity and I wanted to edit it in a <input text> field separating the elements with commas. Maybe there's a better solution for this ... but the Form component is not my strong suit.
I've had a case with bank account numbers, people tend to enter them with spaces in between, we basically have a transformer that does a 1 way "clean-up" when posting the data and keeps this information. Might be a nice example too.
@iltar The issue with the bank account number example again is that it only works well in one direction (you cannot add back removed spaces).
I like Javier's example with tags (we already some parts in the docs that use tags as an example too and this also is something that is easy to understand).
@javiereguiluz :+1:
How about a telephone number?
TextType. People might enter the number with spaces, with dashes, without delimiter, mixed, etc.
In the model data we want the number without spaces/dashes, in the view we present it with spaces.
Simplified example:
class PhoneNumberDataTransformer
{
public function transform($value)
{
return join(' ', str_split($value, 3));
}
public function reverseTransform($value)
{
return str_replace([' ', '-', '–'], '', $value);
}
}
@xabbuh that's correct and the reason I propose that, is because the documentation currently do not have a clear explanation on where to add input normalization into a specific format after submitting (or maybe it got added now). I think this is done with a view transformer.
I like the tags example that @javiereguiluz mentioned :+1: Much simpler to edit with a simple text field in the view rather than using a collection with JS adding/removing with prototypes etc. but we keep the flexibility of separating the tags in the model with an array/collection.
@iltar We may have to make that more clear. But the use case you described should be handled in an event listener.
@webmozart has a nice talk about forms where he explains that quite well:
Data transformers should never change the information stored in a form, but only the data's representation.
To change information, use events.
Let's implement the implode/explode one suggested by @javiereguiluz
I'll try to work on this one!
Most helpful comment
I'll try to work on this one!