Sluggable

← Sluggable

Ashterix

docs: Doctrine section with Doctrine Behaviors and Doctrine Helper (uk + en)

en/docs/doctrine/doctrine-behaviors/sluggable.md new file +74 −0

1 + # Sluggable
2 +
3 + Generates a slug — a URL part like `/post/introduction-to-php` — from one or more entity fields.
4 +
5 + ## Entity
6 +
7 + ```php
8 + use Doctrine\ORM\Mapping as ORM;
9 + use Ufo\DoctrineBehaviors\Contract\Entity\SluggableInterface;
10 + use Ufo\DoctrineBehaviors\Model\Sluggable\SluggableTrait;
11 +
12 + #[ORM\Entity]
13 + class BlogPost implements SluggableInterface
14 + {
15 + use SluggableTrait;
16 +
17 + #[ORM\Id, ORM\GeneratedValue, ORM\Column]
18 + private ?int $id = null;
19 +
20 + #[ORM\Column]
21 + private string $title = '';
22 +
23 + /**
24 + * @return string[]
25 + */
26 + public function getSluggableFields(): array
27 + {
28 + return ['title'];
29 + }
30 + }
31 + ```
32 +
33 + The bundle maps `slug` (string, nullable) if the field is not mapped yet.
34 +
35 + ## How it works
36 +
37 + On `prePersist` and `preUpdate` `generateSlug()` is called:
38 +
39 + * the value of each field from `getSluggableFields()` is taken from the property, or, if there is none, from the `get<Field>()` method;
40 + * empty values are skipped, the rest are joined with a space and converted by `Symfony\Component\String\Slugger\AsciiSlugger` with the `-` delimiter and in lower case: `Žluťoučký kůň` → `zlutoucky-kun`;
41 + * if all values are empty — `Ufo\DoctrineBehaviors\Exception\SluggableException`.
42 +
43 + By default the slug is regenerated on every entity update.
44 +
45 + ## Uniqueness
46 +
47 + By default uniqueness is not guaranteed. To enable it, override `shouldGenerateUniqueSlugs()`:
48 +
49 + ```php
50 + public function shouldGenerateUniqueSlugs(): bool
51 + {
52 + return true;
53 + }
54 + ```
55 +
56 + Then a `-1`, `-2`, … suffix is added to a taken slug: the check covers rows of the same class in the database (except the entity itself) and entities scheduled in the current `flush()`.
57 +
58 + ## What can be overridden
59 +
60 + | Trait method | Default | Purpose |
61 + | --- | --- | --- |
62 + | `shouldGenerateUniqueSlugs(): bool` | `false` | Add a numeric suffix to a taken slug. |
63 + | `shouldRegenerateSlugOnUpdate(): bool` | `true` | `false` — the slug is generated once and never changes. |
64 + | `getSlugDelimiter(): string` | `-` | Word delimiter. |
65 + | `generateSlugValue(array $values): string` | `AsciiSlugger` | Your own algorithm. |
66 +
67 + All these methods except `shouldGenerateUniqueSlugs()` are private in the trait — the entity simply declares its own method with the same name:
68 +
69 + ```php
70 + private function shouldRegenerateSlugOnUpdate(): bool
71 + {
72 + return false;
73 + }
74 + ```