fbeen / uniqueslugbundle
为您的实体和路由添加简单快捷的唯一别名
V2.2
2019-11-05 19:06 UTC
Requires
- php: ^7.0.8
- ext-intl: *
- doctrine/inflector: ^1.2
- nikic/php-parser: ^4.0
- symfony/config: ^3.4|^4.0
- symfony/console: ^3.4|^4.0
- symfony/dependency-injection: ^3.4|^4.0
- symfony/filesystem: ^3.4|^4.0
- symfony/finder: ^3.4|^4.0
- symfony/framework-bundle: ^3.4|^4.0
- symfony/http-kernel: ^3.4|^4.0
- symfony/maker-bundle: >1.1
This package is not auto-updated.
Last update: 2024-09-18 10:47:57 UTC
README
使用此包,您只需在指定的字段上添加一个@Slug注解,即可自动在实体内部生成唯一的别名。
特性包括
- 非常简单的安装
- 从实体的一个或多个属性或自定义方法中生成唯一的别名
- 自动存储到数据库,始终保证别名唯一
- 必要时通过添加数字来保证别名唯一
- 使用命令提示符添加或重新生成现有表中的别名
- 支持日期、时间和日期时间字段,支持自定义格式
- 支持自定义(特定语言)的别名生成器
要求
此包当前版本需要Symfony 4。您可以使用此包的1.2版本与Symfony >= 2.7一起使用。
已知限制
- 当您将实体持久化到数据库时,将生成别名,这意味着当您创建实体或更新属性时,别名尚未可用或尚未更新。
- 由于这些值将由数据库INSERT命令设置,因此别名不能由实体的主参数(@Id)生成。
- 别名将被截断到别名字段长度减去8(*)个字符!最后的位置用于额外的数字,必要时将使别名唯一。
(*) 默认配置为8,或者根据“完整配置示例”下的'fbeen_unique_slug.maximum_digits'参数设置。
安装
1. 运行composer
$ composer require fbeen/uniqueslugbundle
2. 将别名行为添加到您的实体中
假设您有一个新闻条目实体,用于在您的网站上显示新闻,并且您希望从
$ bin/console make:slug Newsitem title
那么您的实体可能如下所示
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Fbeen\UniqueSlugBundle\Annotation\Slug;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* @ORM\Entity(repositoryClass="App\Repository\NewsitemRepository")
*/
class Newsitem
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=64)
*/
private $title;
/**
* @ORM\Column(type="text")
*/
private $body;
/**
* @ORM\Column(type="datetime")
*/
private $created;
/**
* @Slug("title")
* @ORM\Column(type="string", length=255, unique=true)
*/
private $slug;
public function __construct()
{
$this->created = new \DateTime();
}
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getBody(): ?string
{
return $this->body;
}
public function setBody(string $body): self
{
$this->body = $body;
return $this;
}
public function getCreated(): ?\DateTimeInterface
{
return $this->created;
}
public function setCreated(\DateTimeInterface $created): self
{
$this->created = $created;
return $this;
}
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(string $slug): self
{
$this->slug = $slug;
return $this;
}
}
手动编辑实体时的重要注意事项
- 不要忘记使用
use Fbeen\UniqueSlugBundle\Annotation\Slug;
- 将
@Slug("title")
注解添加到别名属性,以告诉应用程序它应该从属性生成别名 - 添加一个构造函数,将$created属性设置为当前日期和时间
- 在控制台上使用以下命令添加getter和setter,并更新数据库
3. 迁移
将更改应用于数据库
$ bin/console make:migration
$ bin/console doctrine:migrations:migrate
4. 在您的路由中使用别名
从现在开始,如果您持久化实体,别名将自动生成。要使用别名进入路由,您可以在路由中使用$slug属性,例如。
@Route("/{slug}", name="newsitem_show")
然后您必须使用给定的别名检索正确的新闻条目。幸运的是,由于Symfony的自动参数转换,这非常简单。
/**
* @Route("/{slug}", name="newsitem_show", methods={"GET"})
*/
public function show(Newsitem $newsitem): Response
{
return $this->render('newsitem/show.html.twig', [
'newsitem' => $newsitem,
]);
}
当您生成指向show操作的路线时,不要忘记将别名属性传递给路由器
<a href="{{ path('newsitem_show', {'slug': newsitem.slug}) }}">show</a>
高级别名
别名注解还有一些其他功能
-
要从多个属性生成别名,请写出属性的数组:
@Slug({"created", "title"})
-
要为日期、时间和日期时间字段添加您自己的格式,请使用格式参数:
@Slug({"created", "title"}, format="Y-m-d")
。 -
您还可以编写自己的构建别名的函数,并将该函数名应用于@Slug注解。
/**
* @Slug("generateSlug")
* @ORM\Column(type="string", length=255, unique=true)
*/
private $slug;
public function generateSlug()
{
return $this->created->format('Y-m-d') . ' ' . $this->title;
}
更新表中所有记录的别名
使用Symfony控制台命令,您可以为所有记录生成别名
$ php bin/console make:slug Newsitem --regenerate
创建您自定义(特定语言)的slugifier
- 首先编写您自己的slugifier类,并确保您的类实现了
Fbeen\UniqueSlugBundle\Slugifier\SlugifierInterface
接口,例如:
<?php
// App\Service\MyCustomSlugifier.php
namespace App\Service;
use Fbeen\UniqueSlugBundle\Slugifier\SlugifierInterface;
/**
* My custom slugifier
*/
class MyCustomSlugifier implements SlugifierInterface
{
public function slugify($text) : string
{
// replace non letter or digits by -
$text = preg_replace('~[^\\pL\d]+~u', '-', $text);
// trim
$text = trim($text, '-');
// transliterate latin characters
$text = \transliterator_transliterate('Any-Latin; Latin-ASCII; [\u0100-\u7fff] remove', $text);
// lowercase
$text = strtolower($text);
// remove unwanted characters
$text = preg_replace('~[^-\w]+~', '', $text);
if (empty($text))
{
return 'n-a';
}
return $text;
}
}
- 如果您将slugifier放在App\Service目录下,它将作为服务自动注入。如果不是,请添加一个服务定义在您的/config/services.yaml文件中
services:
# Only necessary if autowiring is off
App\Service\MyCustomSlugifier: ~
- 在config/packages目录下添加一个名为fbeen_unique_slug.yaml的配置文件。
# config/packages/fbeen_unique_slug.yaml
fbeen_unique_slug:
slugifier_class: App\Service\MyCustomSlugifier
- 现在您应该在当前bundle的主目录下运行phpunit Tests/SlugifierTest来测试您的slugifier类!(您必须已安装phpunit。请参阅https://phpunit.readthedocs.io/en/8.0/installation.html)
准备好了!从现在开始,slug将通过您的自定义slugifier类生成。
带有默认值的完整配置示例
# config/packages/fbeen_unique_slug.yaml
fbeen_unique_slug:
slugifier_class: 'fbeen_unique_slug.slugifier'
maximum_digits: 8
minimum_slug_length: 16