Symfony 2 - Creating Slugs with Gedmo \ Slug

I just installed doctrine extensions for using Sluggable.

I'm doing it:

composer.json

"stof/doctrine-extensions-bundle": "1.2.*@dev" 

AppKernel.php

 new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(), 

application / Config / config.yml

 stof_doctrine_extensions: orm: default: sluggable: true 

Djoo \ AppliBundle \ Entity \ Nomenclature.php

 namespace Djoo\AppliBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Doctrine\DBAL\Types\SmallIntType; use Gedmo\Mapping\Annotation as Gedmo; /** * Nomenclature * * * @ORM\Table(name="app_nomenclature") * @ORM\Entity */ class Nomenclature { ..... /** * @var string * * @ORM\Column(name="titre", type="string", length=200, nullable=false) */ private $titre; /** * @var string * * @ORM\Column(name="finess", type="string", length=10, nullable=true) */ private $finess; /** * @Gedmo\Slug(fields={"titre","finess"},suffix=".html") * @ORM\Column(length=128, unique=true,nullable=true) */ private $slug; public function getSlug() { return $this->slug; } public function setSlug($slug){ $this->slug = $slug; return $this; } } 

In my controller, I do this to generate slug for old values ​​in my datatable:

 $filterBuilder = $this->get('doctrine.orm.entity_manager')>getRepository('DjooAppliBundle:Nomenclature')->createQueryBuilder('e')->orderBy('e.titre', 'asc'); $query = $filterBuilder->getQuery(); $nomenclatures = $query->getResult(); foreach($nomenclatures as $nomenclaturee){ $nomenclature->setSlug(null); $this->get('doctrine.orm.entity_manager')->persist($nomenclature); $this->get('doctrine.orm.entity_manager')->flush(); } 

I have no error, but my old values ​​are an empty pool. I am trying to create a new element and I have a good slug. Do you have an idea?

thanks

+6
source share
4 answers

To change the pool, you must change the associated property. You can add a space at the end of the $titre , save it, change it and save it again. This will clear the slugs.

+7
source
 $uow = $em->getUnitOfWork(); $uow->propertyChanged($entity, 'slug', NULL, NULL); $uow->scheduleForUpdate($entity); $em->flush(); 
+2
source

The sluggable documentation states the following:

If you want slug to be updated based on sluggable fields, set slug to null.

 <?php $entity = $em->find('Entity\Something', $id); $entity->setSlug(null); $em->persist($entity); $em->flush(); 

This works for me.

+2
source

Why this did not work for the OP, but it worked for others (e.g. @gregor):

When creating slug, your first instinct is to create the slug property with this column configuration:

  .. @ORM\Column(unique=true, nullable=false) private $slug; .. 

When you run app/console doctrine:schema:update and this will lead to 2 sql statements:

 ALTER TABLE ... ADD slug ... NOT NULL CREATE UNIQUE INDEX...`. 

By default, the slug column will be filled with the value '' (empty row), which will lead to the error of the 2nd statement with the error ( Duplicate entry '' ). You now have two options:

Option A: Ignore Second Operator Failure

If you ignore the error and later try to create bullets manually using the documented method $entity->setSlug(null) , everything will work. This would work because using $entity->setSlug(null) , you would let Doctrine know that the slug property has been changed (from '' to null ), and this in turn will cause internal $uow->propertyChanged() and $uow->scheduleForUpdate() (thanks to @Sebastian Rad for his example). The Sluggable extension Sluggable also notice this change and will regenerate the slug. Now that all the bullets are unique, the next time you run app/console doc:schema:update it will be able to create an index on slug and your circuit will be fully synchronized.

Choice B: Change the slug field to nullable After you notice an error, your instinct should mark the slug field as nullable , so creating the index will succeed:

  .. @ORM\Column(unique=true, nullable=true) private $slug; .. 

This will cause the slug column to be null as the default value. Now, when you try to use the documented approach $entity->setSlug(null) , it will not work (just like the OP published). This is because when the $entity->slug property is already null . Thus, when you use $entity->setSlug(null) , Doctrine does not detect any changes, and therefore the Sluggable regeneration behavior never fires. To trigger the changes, there were two answers:

  • hack by adding space to source properties slug $entity -> setTitre($titre." "); (but this will result in extra space that you have to crop after)

  • @Sebastian Radu's approach, where he shows how to directly tell the doctrine that the field has been changed (I personally prefer this and wonder why it was unfairly underestimated)

Hope this helps you better understand the inner workings of the Doctrine and extensions.

+2
source

Source: https://habr.com/ru/post/976868/


All Articles