Sluggable behavior will build the slug of predefined fields on a given field which should store the slug
Features:
Update 2012-02-26
Update 2011-09-11
Update 2011-04-04
Update 2010-12-23
Note:
Portability:
This article will cover the basic installation and functionality of Sluggable behavior
Content:
Read the documentation or check the example code on how to setup and use the extensions in most optimized way.
Note: that Sluggable interface is not necessary, except in cases there you need to identify entity as being Sluggable. The metadata is loaded only once then cache is activated
Note: 2.0.x version of extensions used @Gedmo\Mapping\Annotation\Sluggable to identify the field for slug
<?php
namespace Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="articles")
* @ORM\Entity
*/
class Article
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(length=64)
*/
private $title;
/**
* @ORM\Column(length=16)
*/
private $code;
/**
* @Gedmo\Slug(fields={"title", "code"})
* @ORM\Column(length=128, unique=true)
*/
private $slug;
public function getId()
{
return $this->id;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
public function setCode($code)
{
$this->code = $code;
}
public function getCode()
{
return $this->code;
}
public function getSlug()
{
return $this->slug;
}
}
<?php
namespace Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* @ODM\Document(collection="articles")
*/
class Article
{
/**
* @ODM\Id
*/
private $id;
/**
* @ODM\String
*/
private $title;
/**
* @ODM\String
*/
private $code;
/**
* @Gedmo\Slug(fields={"title", "code"})
* @ODM\String
*/
private $slug;
public function getId()
{
return $this->id;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
public function setCode($code)
{
$this->code = $code;
}
public function getCode()
{
return $this->code;
}
public function getSlug()
{
return $this->slug;
}
}
Yaml mapped Article: /mapping/yaml/Entity.Article.dcm.yml
---
Entity\Article:
type: entity
table: articles
id:
id:
type: integer
generator:
strategy: AUTO
fields:
title:
type: string
length: 64
code:
type: string
length: 16
slug:
type: string
length: 128
gedmo:
slug:
separator: _
style: camel
fields:
- title
- code
indexes:
search_idx:
columns: slug
Note: xml driver is not yet adapted for single slug mapping
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping">
<entity name="Entity\Article" table="sluggables">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="title" type="string" length="128"/>
<field name="code" type="string" length="16"/>
<field name="ean" type="string" length="13"/>
<field name="slug" type="string" length="156" unique="true">
<gedmo:slug unique="true" style="camel" updatable="false" separator="_" fields="title,code,ean" />
</field>
</entity>
</doctrine-mapping>
<?php
$article = new Article();
$article->setTitle('the title');
$article->setCode('my code');
$this->em->persist($article);
$this->em->flush();
echo $article->getSlug();
// prints: the-title-my-code
<?php
class Article
{
// ...
/**
* @Gedmo\Slug(fields={"title"}, style="camel", separator="_", updatable=false, unique=false)
* @Doctrine\ORM\Mapping\Column(length=128, unique=true)
*/
private $slug;
// ...
// ...
/**
* @Doctrine\ORM\Mapping\Column(length=128)
*/
private $title;
// ...
}
And now test the result:
<?php
$article = new Article();
$article->setTitle('the title');
$article->setCode('my code');
$this->em->persist($article);
$this->em->flush();
echo $article->getSlug();
// prints: The_Title_My_Code
To set your own custom transliterator, which would be used to generate the slug, use:
<?php
$callable = array('My\Class', 'transliterationMethod');
$sluggableListener->setTransliterator($callable);
// or use a closure
$callable = function($text, $separatorUsed, $objectBeingSlugged) {
// ...
return $transliteratedText;
};
$sluggableListener->setTransliterator($callable);
In case if you want the slug to regenerate itself based on sluggable fields. Set the slug to null or empty string.
<?php
$entity = $em->find('Entity\Something', $id);
$entity->setSlug('');
$em->persist($entity);
$em->flush();
Sometimes you might need to set it manually, etc if generated one does not look satisfying enough. Sluggable will ensure uniqueness of the slug.
<?php
$entity = new SomeEntity;
$entity->setSluggableField('won't be taken into account');
$entity->setSlug('the required slug, set manually');
$em->persist($entity);
$em->flush();
echo $entity->getSlug(); // outputs: "the-required-slug-set-manually"
If you want to attach TranslationListener also add it to EventManager after the SluggableListener. It is important because slug must be generated first before the creation of it`s translation.
<?php
$evm = new \Doctrine\Common\EventManager();
$sluggableListener = new \Gedmo\Sluggable\SluggableListener();
$evm->addEventSubscriber($sluggableListener);
$translatableListener = new \Gedmo\Translatable\TranslationListener();
$translatableListener->setTranslatableLocale('en_us');
$evm->addEventSubscriber($translatableListener);
// now this event manager should be passed to entity manager constructor
And the Entity should look like:
<?php
namespace Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="articles")
* @ORM\Entity
*/
class Article
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @Gedmo\Translatable
* @ORM\Column(length=64)
*/
private $title;
/**
* @Gedmo\Translatable
* @ORM\Column(length=16)
*/
private $code;
/**
* @Gedmo\Translatable
* @Gedmo\Slug(fields={"title", "code"})
* @ORM\Column(length=128, unique=true)
*/
private $slug;
/**
* @ORM\Column(type="string", length=64)
*/
private $uniqueTitle;
/**
* @Gedmo\Slug(fields={"uniqueTitle"})
* @ORM\Column(type="string", length=128, unique=true)
*/
private $uniqueSlug;
public function getId()
{
return $this->id;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
public function setCode($code)
{
$this->code = $code;
}
public function getCode()
{
return $this->code;
}
public function getSlug()
{
return $this->slug;
}
public function getUniqueSlug()
{
return $this->uniqueSlug;
}
}
Now the generated slug will be translated by Translatable behavior
Any suggestions on improvements are very welcome