-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to restrict adding duplicate tags? #162
Comments
@tetranz any suggestions here? |
It's been a long time since I've done anything with tags but I had a quick play with this today. I think duplicate tags are something you need to deal with in your own code when you persist the tag object. If you detect that the tag is new, you need to do a query or something to check if that unique value already exists and if it does, don't try to add it. |
@tetranz thanks for your reply, seems to me the bundle itself does the add new tag, all I had done on my side was to enable the add new feature with:
How can i do those verifications on my form? |
The bundle creates an instance of the new tag entity but it doesn't persist it to the database. In my controller I added this:
That persists new tags. I can't reproduce your problem if a tag with that name already exists. The tags in region that are returned from As I would expect, I can reproduce your problem if I open my app in another browser tab. I add a new tag in one tab but don't submit the form. Now add the same tag in the other tab and submit the form. Now go back to the other tab and submit. That reproduces the problem because both submits are trying to add the same tag. I don't think that is what you're referring to but I fixed that with this:
That checks if the new tag already exists and substitutes the tag saved moments ago by the other browser tab / user. Even that's not perfect because it is not an atomic operation so you could still get an error with unfortunate timing between two users. You really need a try / catch around the But somehow you seem to be having a more general problem of simple selecting a tag that already exists. I'm not sure what happening for you. The Tag field on my form has this:
|
@tetranz Appreciate your assistance, in my case I use the bundle to add tags to an entity like:
I have no check inside the form, other than this: ` $form->handleRequest($request);
` |
->add('tags', Select2EntityType::class, [ namespace App\Component\DataTransformer; class EntitiesToPropertyTransformer extends \Tetranz\Select2EntityBundle\Form\DataTransformer\EntitiesToPropertyTransformer
// if (count($entities) != count($values)) {
} |
Thanks for this solution @moldwebs, you should better format it ;) It works to don't have duplicates tags in DB. Think to add Add transformer to your form: ...
->add('tags', Select2EntityType::class, [
'label' => 'Tags',
'placeholder' => '',
'class' => TxTag::class,
'primary_key' => 'id',
'text_property' => 'title',
'multiple' => true,
'allow_add' => [
'enabled' => true,
'new_tag_text' => ' ',
'new_tag_prefix' => '__',
'tag_separators' => '[","]'
],
'transformer' => EntitiesToPropertyTransformer::class
])
... Create your new transformer: <?php
namespace App\Form\DataTransform;
use Doctrine\Persistence\ObjectManager;
class EntitiesToPropertyTransformer extends \Tetranz\Select2EntityBundle\Form\DataTransformer\EntitiesToPropertyTransformer
{
/**
* EntitiesToPropertyTransformer constructor.
*
* @param ObjectManager $em
* @param $class
* @param null $textProperty
* @param string $primaryKey
* @param string $newTagPrefix
* @param string $newTagText
*/
public function __construct(ObjectManager $em, $class, $textProperty = null, $primaryKey = 'id', $newTagPrefix = '__', $newTagText = ''){
// Reconstruct parent to prevent $newTagText to be null (because we set empty string in config file) and get a bad value in parent constructor
parent::__construct($em, $class, $textProperty, $primaryKey, $newTagPrefix, $newTagText);
}
/**
* Transform array to a collection of entities
*
* @param array $values
* @return array
*/
public function reverseTransform($values)
{
// Should always be a collection (array)
if (!is_array($values) || empty($values)) {
return [];
}
$newObjects = array();
$newTagPrefixLength = strlen($this->newTagPrefix);
foreach ($values as $key => $value) {
$cleanValue = strtolower(trim(substr($value, $newTagPrefixLength)));
$valuePrefix = substr($value, 0, $newTagPrefixLength);
// If it's a tag that should be added to DB
if ($valuePrefix === $this->newTagPrefix) {
// Search for tag presence in DB
$entity = $this->em->createQueryBuilder()
->select('entity')
->from($this->className, 'entity')
->where('entity.'.$this->textProperty.' = :value')
->setParameter('value', $cleanValue)
->getQuery()
->getOneOrNullResult();
// If tag already exist in DB
if ($entity) {
$values[$key] = $entity->getId();
}
// Transform new and non-existent tag into new Object
else {
$object = new $this->className;
$this->accessor->setValue($object, $this->textProperty, $cleanValue);
$newObjects[] = $object;
unset($values[$key]);
}
}
}
// Get each tags already presents before
$entities = $this->em->createQueryBuilder()
->select('entity')
->from($this->className, 'entity')
->where('entity.'.$this->primaryKey.' IN (:ids)')
->setParameter('ids', $values)
->getQuery()
->getResult();
return array_merge($entities, $newObjects);
}
} |
Hello,
I'm using the add new tag option, but if we have this existing tag: Test tag and someone comes and type test tag I get an error like:
Integrity constraint violation: 1062 Duplicate entry 'test tag' for key 'UNIQ_5E3DE4775E237E06'
Any idea?
The text was updated successfully, but these errors were encountered: