Reputation: 15837
So, here's my situation. I've 3 tables, tag
, product
and tag_product
, which is created from annotations of a "many-to-many" relationship between tag
and product
, i.e. a tag
can be associated with many products and a product can have many tags associated with it.
Now, I'm using a data transformer to transform the Tag
objects to a string composed of the tags separate by commas whenever the user wants to edit a product.
In the Tag
entity I've a primary key, an id, and a unique field, the name of the tag. I don't essentially want to have two tags with the same name.
My problem is that I don't know how to access the "new" tags chosen by the user when the form has been submitted to update the product. Is there a way to do it? Accessing the request may only be useful to access the input string of tags, but not the Tag
objects created from that string in the data transformer.
I could also pass the current $product
object to buildForm
, which would pass it to the data transformer mentioned above, but this doesn't seem a good solution, when an object is passed around (at least to me). Also I would need to create another entity manager from the data transformer and do things that a data transformer shouldn't do.
Any better ideas?
Edit
I've just thought that maybe I could just check when inserting the tag in the ArrayCollection
of the product if that same ArrayCollection
already contains a tag with the same name of the being inserted tag, but since I don't know if that collection will be already filled with the current tags or not, at that moment...
Edit 2
The solution in the previous edit doesn't work for me, I guess, again, because that array collection is empty when the new tag is inserted...
Upvotes: 1
Views: 3707
Reputation: 10638
Not sure if this is best practice, but what I have done in the past is use the following ModelTransformer
// ArrayCollection of tags to string
function ($tags)
{
if ($tags === null)
return '';
return implode(',', array_map(function($tag){
return $tag->getName();
}, $tags->toArray()));
}
// string to ArrayCollection of tags
function ($string)
{
$tags = new \Doctrine\Common\Collections\ArrayCollection();
if ($string === '' || $string === null)
return $tags;
$array = explode(',', $string);
foreach ($array as $tagName) {
$tag = $this->em
->getRepository('AppBundle:Tag')
->findOrCreateByName($tagName);
$tags->add($tag);
}
return $tags;
}
Where the key actually is the findOrCreateByName()
method in the TagRepository
public function findOrCreateByName($name)
{
$name = trim($name);
$tag = self::findOneBy(['name' => $name]);
if ($tag === null) {
$tag = new Tag;
$tag->setName($name);
}
return $tag;
}
Upvotes: 1