fbeen/uniqueslugbundle

为您的实体和路由添加简单快捷的唯一别名

安装: 3,525

依赖关系: 0

建议者: 0

安全性: 0

星级: 4

关注者: 2

分支: 4

类型:symfony-bundle

V2.2 2019-11-05 19:06 UTC

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. 将别名行为添加到您的实体中

假设您有一个新闻条目实体,用于在您的网站上显示新闻,并且您希望从属性生成别名。</p> <pre class="notranslate"><code> $ bin/console make:slug Newsitem title </code></pre> <p>那么您的实体可能如下所示</p> <pre class="notranslate"><code><?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; } } </code></pre> <p><strong>手动编辑实体时的重要注意事项</strong></p> <ul> <li>不要忘记使用<code>use Fbeen\UniqueSlugBundle\Annotation\Slug;</code></li> <li>将<code>@Slug("title")</code>注解添加到别名属性,以告诉应用程序它应该从<title>属性生成别名</li> <li>添加一个构造函数,将$created属性设置为当前日期和时间</li> <li>在控制台上使用以下命令添加getter和setter,并更新数据库</li> </ul> <h3 class="heading-element">3. 迁移</h3><a id="user-content-3-migrate" class="anchor" href="#user-content-3-migrate" rel="nofollow noindex noopener external ugc"></a> <p>将更改应用于数据库</p> <pre class="notranslate"><code> $ bin/console make:migration $ bin/console doctrine:migrations:migrate </code></pre> <h3 class="heading-element">4. 在您的路由中使用别名</h3><a id="user-content-4-using-the-slugs-in-your-routes" class="anchor" href="#user-content-4-using-the-slugs-in-your-routes" rel="nofollow noindex noopener external ugc"></a> <p>从现在开始,如果您持久化实体,别名将自动生成。要使用别名进入路由,您可以在路由中使用$slug属性,例如。</p> <pre class="notranslate"><code> @Route("/{slug}", name="newsitem_show") </code></pre> <p>然后您必须使用给定的别名检索正确的新闻条目。幸运的是,由于Symfony的自动参数转换,这非常简单。</p> <pre class="notranslate"><code> /** * @Route("/{slug}", name="newsitem_show", methods={"GET"}) */ public function show(Newsitem $newsitem): Response { return $this->render('newsitem/show.html.twig', [ 'newsitem' => $newsitem, ]); } </code></pre> <p>当您生成指向show操作的路线时,不要忘记将别名属性传递给路由器</p> <pre class="notranslate"><code> <a href="{{ path('newsitem_show', {'slug': newsitem.slug}) }}">show</a> </code></pre> <h2 class="heading-element">高级别名</h2><a id="user-content-advanced-slugs" class="anchor" href="#user-content-advanced-slugs" rel="nofollow noindex noopener external ugc"></a> <p>别名注解还有一些其他功能</p> <ol> <li> <p>要从多个属性生成别名,请写出属性的数组:<code>@Slug({"created", "title"})</code></p> </li> <li> <p>要为日期、时间和日期时间字段添加您自己的格式,请使用格式参数:<code>@Slug({"created", "title"}, format="Y-m-d")</code>。</p> </li> <li> <p>您还可以编写自己的构建别名的函数,并将该函数名应用于@Slug注解。</p> </li> </ol> <pre class="notranslate"><code> /** * @Slug("generateSlug") * @ORM\Column(type="string", length=255, unique=true) */ private $slug; public function generateSlug() { return $this->created->format('Y-m-d') . ' ' . $this->title; } </code></pre> <h2 class="heading-element">更新表中所有记录的别名</h2><a id="user-content-update-the-slugs-for-all-records-of-your-table" class="anchor" href="#user-content-update-the-slugs-for-all-records-of-your-table" rel="nofollow noindex noopener external ugc"></a> <p>使用Symfony控制台命令,您可以为所有记录生成别名</p> <pre class="notranslate"><code> $ php bin/console make:slug Newsitem --regenerate </code></pre> <h2 class="heading-element">创建您自定义(特定语言)的slugifier</h2><a id="user-content-create-your-custom-language-specific-slugifier" class="anchor" href="#user-content-create-your-custom-language-specific-slugifier" rel="nofollow noindex noopener external ugc"></a> <ol> <li>首先编写您自己的slugifier类,并确保您的类实现了<code>Fbeen\UniqueSlugBundle\Slugifier\SlugifierInterface</code>接口,例如:</li> </ol> <pre class="notranslate"><code><?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; } } </code></pre> <ol> <li>如果您将slugifier放在App\Service目录下,它将作为服务自动注入。如果不是,请添加一个服务定义在您的<em><strong>/config/services.yaml</strong></em>文件中</li> </ol> <pre class="notranslate"><code>services: # Only necessary if autowiring is off App\Service\MyCustomSlugifier: ~ </code></pre> <ol> <li>在<em><strong>config/packages</strong></em>目录下添加一个名为<em><strong>fbeen_unique_slug.yaml</strong></em>的配置文件。</li> </ol> <pre class="notranslate"><code># config/packages/fbeen_unique_slug.yaml fbeen_unique_slug: slugifier_class: App\Service\MyCustomSlugifier </code></pre> <ol> <li>现在您应该在当前bundle的主目录下运行<em><strong>phpunit Tests/SlugifierTest</strong></em>来测试您的slugifier类!(您必须已安装phpunit。请参阅<a href="https://phpunit.readthedocs.io/en/8.0/installation.html" rel="nofollow noindex noopener external ugc">https://phpunit.readthedocs.io/en/8.0/installation.html</a>)</li> </ol> <p>准备好了!从现在开始,slug将通过您的自定义slugifier类生成。</p> <h2 class="heading-element">带有默认值的完整配置示例</h2><a id="user-content-full-configuration-example-with-default-values" class="anchor" href="#user-content-full-configuration-example-with-default-values" rel="nofollow noindex noopener external ugc"></a> <pre class="notranslate"><code># config/packages/fbeen_unique_slug.yaml fbeen_unique_slug: slugifier_class: 'fbeen_unique_slug.slugifier' maximum_digits: 8 minimum_slug_length: 16 </code></pre> </div> </div> </div> </section> </section> </section> <footer class="wrapper-footer"> <nav class="container"> <div class="row"> <ul class="social col-xs-7 col-sm-4 col-md-2 pull-right"> <li><a href="http://github.com/composer/packagist" title="GitHub"><span class="icon-github"></span></a></li> <li><a href="https://twitter.com/packagist" title="Follow @packagist"><span class="icon-twitter"></span></a></li> <li><a href="mailto:contact@packagist.org" title="Contact"><span class="icon-mail"></span></a></li> </ul> <ul class="col-xs-4 col-sm-4 col-md-2"> <li><a href="/about">About Packagist</a></li> <li><a href="/feeds/" rel="nofollow">Atom/RSS Feeds</a></li> </ul> <div class="clearfix visible-xs-block"></div> <ul class="col-xs-3 col-sm-4 col-md-2"> <li><a href="/statistics" rel="nofollow">Statistics</a></li> <li><a href="/explore/">Browse Packages</a></li> </ul> <div class="clearfix visible-xs-block visible-sm-block"></div> <ul class="col-xs-3 col-sm-4 col-md-2"> <li><a href="/apidoc">API</a></li> <li><a href="/mirrors">Mirrors</a></li> </ul> <div class="clearfix visible-xs-block"></div> <ul class="col-xs-3 col-sm-4 col-md-2"> <li><a href="https://status.packagist.org/">Status</a></li> <li><a href="https://p.datadoghq.com/sb/x98w56x71erzshui-4a54c45f82bacc991e83302548934b6a">Dashboard</a></li> </ul> </div> <div class="row sponsor"> <p class="col-xs-12">Packagist maintenance and hosting provided by <a href="https://packagist.com/"><img alt="Private Packagist" src="/img/private-packagist.svg?v=1726064759"></a></p> </div> <div class="row sponsor"> <p class="col-xs-12">Monitoring provided by <a href="https://datadog.com/"><img alt="Datadog" src="/img/datadog-light.png?v=1726064759"></a></p> </div> </nav> </footer> <script nonce="2i2jmjrxPQE9WrGPLIKC1w=="> var algoliaConfig = {"app_id":"M58222SH95","search_key":"5ae4d03c98685bd7364c2e0fd819af05","index_name":"packagist"}; window.process = { env: { DEBUG: undefined }, }; </script> <script nonce="2i2jmjrxPQE9WrGPLIKC1w==" src="/build/app.js?v=1726064759"></script> </body></html>