Reputation: 137
I have just installed the doctrine extensions to use Sluggable.
I make this :
composer.json
"stof/doctrine-extensions-bundle": "1.2.*@dev"
AppKernel.php
new Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle(),
app/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 make 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 a null slug. I try to create a new element and i have a good slug. Have you and idea ?
Thanks
Upvotes: 7
Views: 10419
Reputation: 2356
When creating slug, your first instinct is to create slug property with this column configuration:
..
@ORM\Column(unique=true, nullable=false)
private $slug;
..
When running app/console doctrine:schema:update
and this will result in 2 sql statements:
ALTER TABLE ... ADD slug ... NOT NULL
CREATE UNIQUE INDEX...`.
By default column slug
will be filled with value ''
(empty string) which would make 2nd statement to fail with (Duplicate entry ''
) error. Now you have two choices:
Choice A: Ignore failure of the 2nd statement
If you ignore the error, and later try generating slugs manually using the documented method $entity->setSlug(null)
everything would work. It would work because by using $entity->setSlug(null)
you would let Doctrine know that propertyslug
was changed (from ''
to null
) and this in turn would trigger internally $uow->propertyChanged()
and $uow->scheduleForUpdate()
(Thanks to @Sebastian Radu for his example). The Sluggable
extension will notice this change as well and will regenerate the slug. Now as all the slugs are unique, next time you run app/console doc:schema:update
it will succeed in creating index on slug
and your schema will be fully in sync.
Choice B: Modify slug
field to be nullable
After noticing error your instinct would be to mark slug
field as nullable
, so that index creation succeeds:
..
@ORM\Column(unique=true, nullable=true)
private $slug;
..
This would result in slug
column having NULL
as it's default value. Now as you try using documented $entity->setSlug(null)
approach it won't work (just as OP has posted). This happens because when $entity->slug
property is already NULL
. Thus when you use $entity->setSlug(null)
no changes are detected by Doctrine, and thus Sluggable
regeneration behaviour is never triggered. In order to trigger the changes there were two answers:
hack with adding space to the slug source properties $entity -> setTitre($titre." ");
(but this would result in extra space you would have to trim after)
approach by @Sebastian Radu, where he shows how to tell Doctrine directly that the field was changed (I personally prefer this one and wonder why it was unfairly downvoted)
Hope this helps you understand a bit better the inner workings of Doctrine and extensions.
Upvotes: 3
Reputation: 558
The sluggable documentation states the following:
In case if you want the slug to regenerate itself based on sluggable fields, set the slug to null.
<?php $entity = $em->find('Entity\Something', $id); $entity->setSlug(null); $em->persist($entity); $em->flush();
It does work for me.
Upvotes: 2
Reputation: 76
$uow = $em->getUnitOfWork();
$uow->propertyChanged($entity, 'slug', NULL, NULL);
$uow->scheduleForUpdate($entity);
$em->flush();
Upvotes: 4
Reputation: 2488
To change the slug you must change the related property. You can add a space at the end of $titre
, save it, change it back and save it again. That will flush the slugs.
Upvotes: 7