【问题标题】:drupal: standard way for creating a slug from a stringdrupal:从字符串创建 slug 的标准方法
【发布时间】:2011-02-21 07:53:31
【问题描述】:

此上下文中的 slug 是一个字符串,它可以安全地用作标识符,在 url 或 css 上。例如,如果你有这个字符串:

I'd like to eat at McRunchies!

它的蛞蝓是:

i-d-like-to-eat-at-mcrunchies

我想知道是否有在 Drupal(或 drupal 提供的 php 函数)上构建此类字符串的标准方法。更准确地说,在 Drupal 主题中。

上下文:我正在修改一个drupal 主题,因此它生成的节点的html 将它们的分类术语作为css 类包含在其包含的div 上。麻烦的是,其中一些术语的名称不是有效的 css 类名称。我需要“扼杀”他们。

我读到有些人只是这样做:

str_replace(" ", "-", $term->name)

这对我来说还不够。它不会用小写字母替换大写字母,但更重要的是,不会用它们的 ascii 等效字符替换非 ascii 字符(如 à 或 é)。它也不会从开头和结尾删除“分隔符字符串”。

drupal 6(或 php 库)中是否有一个函数提供了一种对字符串进行 slugify 的方法,并且可以在 drupal 主题的 template.php 文件中使用?

【问题讨论】:

    标签: php string drupal slug


    【解决方案1】:

    您可以使用内置的 Drupal 函数来执行此操作。

    $string = drupal_clean_css_identifier($string);
    $slug = drupal_html_class($string);
    

    函数会为您解决问题。

    【讨论】:

    • 我在下面添加了 Drupal 8/9 方式作为答案
    【解决方案2】:

    我是一个快乐的 Zen 主题用户,因此我遇到了它附带的这个奇妙的功能:zen_id_safe http://api.lullabot.com/zen_id_safe

    它不依赖于任何其他主题功能,因此您可以将其复制到您的模块或主题中并使用它。这是一个非常小而简单的功能,所以为了方便起见,我将它粘贴在这里。

    function zen_id_safe($string) {
      // Replace with dashes anything that isn't A-Z, numbers, dashes, or underscores.
      return strtolower(preg_replace('/[^a-zA-Z0-9-]+/', '-', $string));
    }

    【讨论】:

    • 这几乎是我所需要的。但是,它不会音译,也不会从一开始就删除分隔符。无论如何,感谢您花时间回答。
    • 您可以添加删除分隔符的逻辑(请注意,这只是 id 的要求,因为类可以使用所有内容(请参阅barney.w3.org/TR/REC-html40/struct/global.html#adef-class 并单击 cdata-list)。至于正确的音译,请参阅我对 googletorp 的回答的评论。
    【解决方案3】:

    我最终使用了slug函数explained here(在文章末尾,您必须单击才能看到源代码)。

    这可以满足我的需要以及更多功能,而无需包含外部模块等。

    粘贴下面的代码以方便日后参考:

    /**
     * Calculate a slug with a maximum length for a string.
     *
     * @param $string
     *   The string you want to calculate a slug for.
     * @param $length
     *   The maximum length the slug can have.
     * @return
     *   A string representing the slug
     */
    function slug($string, $length = -1, $separator = '-') {
      // transliterate
      $string = transliterate($string);
     
      // lowercase
      $string = strtolower($string);
     
      // replace non alphanumeric and non underscore charachters by separator
      $string = preg_replace('/[^a-z0-9]/i', $separator, $string);
     
      // replace multiple occurences of separator by one instance
      $string = preg_replace('/'. preg_quote($separator) .'['. preg_quote($separator) .']*/', $separator, $string);
     
      // cut off to maximum length
      if ($length > -1 && strlen($string) > $length) {
        $string = substr($string, 0, $length);
      }
     
      // remove separator from start and end of string
      $string = preg_replace('/'. preg_quote($separator) .'$/', '', $string);
      $string = preg_replace('/^'. preg_quote($separator) .'/', '', $string);
     
      return $string;
    }
     
    /**
     * Transliterate a given string.
     *
     * @param $string
     *   The string you want to transliterate.
     * @return
     *   A string representing the transliterated version of the input string.
     */
    function transliterate($string) {
      static $charmap;
      if (!$charmap) {
        $charmap = array(
          // Decompositions for Latin-1 Supplement
          chr(195) . chr(128) => 'A', chr(195) . chr(129) => 'A',
          chr(195) . chr(130) => 'A', chr(195) . chr(131) => 'A',
          chr(195) . chr(132) => 'A', chr(195) . chr(133) => 'A',
          chr(195) . chr(135) => 'C', chr(195) . chr(136) => 'E',
          chr(195) . chr(137) => 'E', chr(195) . chr(138) => 'E',
          chr(195) . chr(139) => 'E', chr(195) . chr(140) => 'I',
          chr(195) . chr(141) => 'I', chr(195) . chr(142) => 'I',
          chr(195) . chr(143) => 'I', chr(195) . chr(145) => 'N',
          chr(195) . chr(146) => 'O', chr(195) . chr(147) => 'O',
          chr(195) . chr(148) => 'O', chr(195) . chr(149) => 'O',
          chr(195) . chr(150) => 'O', chr(195) . chr(153) => 'U',
          chr(195) . chr(154) => 'U', chr(195) . chr(155) => 'U',
          chr(195) . chr(156) => 'U', chr(195) . chr(157) => 'Y',
          chr(195) . chr(159) => 's', chr(195) . chr(160) => 'a',
          chr(195) . chr(161) => 'a', chr(195) . chr(162) => 'a',
          chr(195) . chr(163) => 'a', chr(195) . chr(164) => 'a',
          chr(195) . chr(165) => 'a', chr(195) . chr(167) => 'c',
          chr(195) . chr(168) => 'e', chr(195) . chr(169) => 'e',
          chr(195) . chr(170) => 'e', chr(195) . chr(171) => 'e',
          chr(195) . chr(172) => 'i', chr(195) . chr(173) => 'i',
          chr(195) . chr(174) => 'i', chr(195) . chr(175) => 'i',
          chr(195) . chr(177) => 'n', chr(195) . chr(178) => 'o',
          chr(195) . chr(179) => 'o', chr(195) . chr(180) => 'o',
          chr(195) . chr(181) => 'o', chr(195) . chr(182) => 'o',
          chr(195) . chr(182) => 'o', chr(195) . chr(185) => 'u',
          chr(195) . chr(186) => 'u', chr(195) . chr(187) => 'u',
          chr(195) . chr(188) => 'u', chr(195) . chr(189) => 'y',
          chr(195) . chr(191) => 'y',
          // Decompositions for Latin Extended-A
          chr(196) . chr(128) => 'A', chr(196) . chr(129) => 'a',
          chr(196) . chr(130) => 'A', chr(196) . chr(131) => 'a',
          chr(196) . chr(132) => 'A', chr(196) . chr(133) => 'a',
          chr(196) . chr(134) => 'C', chr(196) . chr(135) => 'c',
          chr(196) . chr(136) => 'C', chr(196) . chr(137) => 'c',
          chr(196) . chr(138) => 'C', chr(196) . chr(139) => 'c',
          chr(196) . chr(140) => 'C', chr(196) . chr(141) => 'c',
          chr(196) . chr(142) => 'D', chr(196) . chr(143) => 'd',
          chr(196) . chr(144) => 'D', chr(196) . chr(145) => 'd',
          chr(196) . chr(146) => 'E', chr(196) . chr(147) => 'e',
          chr(196) . chr(148) => 'E', chr(196) . chr(149) => 'e',
          chr(196) . chr(150) => 'E', chr(196) . chr(151) => 'e',
          chr(196) . chr(152) => 'E', chr(196) . chr(153) => 'e',
          chr(196) . chr(154) => 'E', chr(196) . chr(155) => 'e',
          chr(196) . chr(156) => 'G', chr(196) . chr(157) => 'g',
          chr(196) . chr(158) => 'G', chr(196) . chr(159) => 'g',
          chr(196) . chr(160) => 'G', chr(196) . chr(161) => 'g',
          chr(196) . chr(162) => 'G', chr(196) . chr(163) => 'g',
          chr(196) . chr(164) => 'H', chr(196) . chr(165) => 'h',
          chr(196) . chr(166) => 'H', chr(196) . chr(167) => 'h',
          chr(196) . chr(168) => 'I', chr(196) . chr(169) => 'i',
          chr(196) . chr(170) => 'I', chr(196) . chr(171) => 'i',
          chr(196) . chr(172) => 'I', chr(196) . chr(173) => 'i',
          chr(196) . chr(174) => 'I', chr(196) . chr(175) => 'i',
          chr(196) . chr(176) => 'I', chr(196) . chr(177) => 'i',
          chr(196) . chr(178) => 'IJ', chr(196) . chr(179) => 'ij',
          chr(196) . chr(180) => 'J', chr(196) . chr(181) => 'j',
          chr(196) . chr(182) => 'K', chr(196) . chr(183) => 'k',
          chr(196) . chr(184) => 'k', chr(196) . chr(185) => 'L',
          chr(196) . chr(186) => 'l', chr(196) . chr(187) => 'L',
          chr(196) . chr(188) => 'l', chr(196) . chr(189) => 'L',
          chr(196) . chr(190) => 'l', chr(196) . chr(191) => 'L',
          chr(197) . chr(128) => 'l', chr(197) . chr(129) => 'L',
          chr(197) . chr(130) => 'l', chr(197) . chr(131) => 'N',
          chr(197) . chr(132) => 'n', chr(197) . chr(133) => 'N',
          chr(197) . chr(134) => 'n', chr(197) . chr(135) => 'N',
          chr(197) . chr(136) => 'n', chr(197) . chr(137) => 'N',
          chr(197) . chr(138) => 'n', chr(197) . chr(139) => 'N',
          chr(197) . chr(140) => 'O', chr(197) . chr(141) => 'o',
          chr(197) . chr(142) => 'O', chr(197) . chr(143) => 'o',
          chr(197) . chr(144) => 'O', chr(197) . chr(145) => 'o',
          chr(197) . chr(146) => 'OE', chr(197) . chr(147) => 'oe',
          chr(197) . chr(148) => 'R', chr(197) . chr(149) => 'r',
          chr(197) . chr(150) => 'R', chr(197) . chr(151) => 'r',
          chr(197) . chr(152) => 'R', chr(197) . chr(153) => 'r',
          chr(197) . chr(154) => 'S', chr(197) . chr(155) => 's',
          chr(197) . chr(156) => 'S', chr(197) . chr(157) => 's',
          chr(197) . chr(158) => 'S', chr(197) . chr(159) => 's',
          chr(197) . chr(160) => 'S', chr(197) . chr(161) => 's',
          chr(197) . chr(162) => 'T', chr(197) . chr(163) => 't',
          chr(197) . chr(164) => 'T', chr(197) . chr(165) => 't',
          chr(197) . chr(166) => 'T', chr(197) . chr(167) => 't',
          chr(197) . chr(168) => 'U', chr(197) . chr(169) => 'u',
          chr(197) . chr(170) => 'U', chr(197) . chr(171) => 'u',
          chr(197) . chr(172) => 'U', chr(197) . chr(173) => 'u',
          chr(197) . chr(174) => 'U', chr(197) . chr(175) => 'u',
          chr(197) . chr(176) => 'U', chr(197) . chr(177) => 'u',
          chr(197) . chr(178) => 'U', chr(197) . chr(179) => 'u',
          chr(197) . chr(180) => 'W', chr(197) . chr(181) => 'w',
          chr(197) . chr(182) => 'Y', chr(197) . chr(183) => 'y',
          chr(197) . chr(184) => 'Y', chr(197) . chr(185) => 'Z',
          chr(197) . chr(186) => 'z', chr(197) . chr(187) => 'Z',
          chr(197) . chr(188) => 'z', chr(197) . chr(189) => 'Z',
          chr(197) . chr(190) => 'z', chr(197) . chr(191) => 's',
          // Euro Sign
          chr(226) . chr(130) . chr(172) => 'E'
        );
      }
     
      // transliterate
      return strtr($string, $charmap);
    }
     
    function is_slug($str) {
      return $str == slug($str);
    }
    

    【讨论】:

      【解决方案4】:

      还有一个来自 d7 的内容,您可以将其复制到您的项目中:

      http://api.drupal.org/api/function/drupal_clean_css_identifier/7

      【讨论】:

      • 很高兴知道drupal 有这样的功能。但是,它并不能满足我的所有需求(请参阅我的其他答案)。但为研究工作 +1。
      【解决方案5】:

      这可能会有所帮助,我发现我现在一直在做这件事,而不是在我的表中使用 id 号作为唯一键。

          /** class SlugMaker
          * 
          * methods to create text slugs for urls
          *
          **/
      
      class SlugMaker {
      
          /** method slugify
          * 
          * cleans up a string such as a page title
          * so it becomes a readable valid url
          *
          * @param STR a string
          * @return STR a url friendly slug
          **/
      
          function slugifyAlnum( $str ){
      
          $str = preg_replace('#[^0-9a-z ]#i', '', $str );    // allow letters, numbers + spaces only
          $str = preg_replace('#( ){2,}#', ' ', $str );       // rm adjacent spaces
          $str = trim( $str ) ;
      
          return strtolower( str_replace( ' ', '-', $str ) ); // slugify
      
      
          }
      
      
          function slugifyAlnumAppendMonth( $str ){
      
          $val = $this->slugifyAlnum( $str );
      
          return $val . '-' . strtolower( date( "M" ) ) . '-' . date( "Y" ) ;
      
          }
      
      }
      

      使用此规则和 .htaccess 规则意味着您可以直接从以下网址访问:

      /articles/my-pops-nuts-may-2010

      直接查找表格,无需取消映射 ID(自然地应用合适的过滤器)。

      选择性地附加或预先添加某种日期,以便根据需要强制执行一定程度的唯一性。

      HTH

      【讨论】:

      • 感谢您发布此信息。我唯一不喜欢这个函数的是它在标识符的开头和结尾留下了分隔符;如果你有#1 - Option 1 之类的东西,它将被转换为-1-option-1,这在css 上使用是不安全的。一个小问题是它不会音译。
      • 支持例如 URL /articles/my-pops-nuts-may-2010
      【解决方案6】:

      对于 Drupal 8/9,您可以使用 Html::getClass

      $slugify = Html::getClass('A @ Stríng-that n+eeds cónvert');
      

      在需要时不要忘记在模块中包含命名空间

      use Drupal\Component\Utility\Html;
      

      【讨论】:

        【解决方案7】:

        我会推荐 path_auto 使用的transliteration module。有了它,您可以使用transliteration_get() 功能。它还进行 unicode 转换。

        【讨论】:

        • pathauto 不使用音译模块。它使用自己的函数 pathauto_cleanstring(),该函数依赖于 pathauto 的大量设置。 drupalcontrib.org/api/function/pathauto_cleanstring/6
        • @barraponto 你可以让 pathauto 使用它来处理 url 中的 unicode,否则处理得不好。
        • 如何让 pathauto 使用音译模块?我一直在寻找那个...stackoverflow.com/questions/2865742/…
        • 感谢您发布此信息。但是,如果可能,我会避免添加额外的模块。我正在寻找由 Drupal 或 PHP 直接提供的东西。
        • 我打赌你已经在使用 pathauto。它有一个内置的音译文件 (i18n-ascii.txt),它将在 pathauto_cleanstring() 中提供音译。你不需要音译模块。
        【解决方案8】:

        经过大量试验和错误后,这对我有用,包括将带有特殊字符的法语和德语标题转换为 slug。

        我创建了一个自定义的树枝过滤器,所以我可以像这样使用它:

        {{ node.field_title.value|slug }}
        

        它会转换:

        Wärmeabgabe & Abmessungen
        Typenübersicht
        Montage- und Anschlussmaße
        

        进入:

        warmeabgabe--abmessungen
        typenubersicht
        montage--und-anschlussmasse
        

        例如。

        方法: 在自定义模块中,创建 services.yml 文件:modules/custom/mymodule/mymodule.services.yml

        services:
         mymodule.twig_extensions:
            class: Drupal\mymodule\HelperTwigExtensions
            tags:
              - { name: twig.extension }
        

        创建modules/custom/mymodule/src/HelperTwigExtensions.php 文件:

        <?php
        
        namespace Drupal\mymodule;
        
        use Drupal\Component\Utility\Html;
        
        /**
         * Extend Drupal's Twig_Extension class.
         */
        class HelperTwigExtensions extends \Twig_Extension {
        
          /**
           * {@inheritdoc}
           */
          public function getName() {
            return 'mymodule.twig_extensions';
          }
        
          /**
           * {@inheritdoc}
           */
          public function getFilters() {
            return [
              new \Twig_SimpleFilter('slug', [$this, 'createSlug']),
            ];
          }
        
          /**
           * Create a slug from a string input.
           */
          public function createSlug($input) {
            // Convert most of the special characters.
            $slug = Html::getClass($input);
            $slug = strtolower($slug);
            // Convert accented text characters.
            $unwanted_array = [
              'Þ' => 'b',
              'ß' => 'ss',
              'à' => 'a',
              'á' => 'a',
              'â' => 'a',
              'ã' => 'a',
              'ä' => 'a',
              'å' => 'a',
              'æ' => 'a',
              'ç' => 'c',
              'è' => 'e',
              'é' => 'e',
              'ê' => 'e',
              'ë' => 'e',
              'ì' => 'i',
              'í' => 'i',
              'î' => 'i',
              'ï' => 'i',
              'ð' => 'o',
              'ñ' => 'n',
              'ò' => 'o',
              'ó' => 'o',
              'ô' => 'o',
              'õ' => 'o',
              'ö' => 'o',
              'ø' => 'o',
              'ù' => 'u',
              'ú' => 'u',
              'û' => 'u',
              'ü' => 'u',
              'ý' => 'y',
              'þ' => 'b',
              'ÿ' => 'y',
            ];
            $slug = strtr($slug, $unwanted_array);
            return $slug;
          }
        
        }
        

        【讨论】:

          【解决方案9】:

          您可以使用 preg_replace 和 strtolower :

          preg_replace('/[^a-z]/','-', strtolower($term->name)); 
          

          【讨论】:

          • 这是干净和简单的。不幸的是,它并不能满足我的所有需求。不过谢谢你的回答。
          • 我刚刚发现基本主题以这种方式实现了您正在寻找的内容: $string = strtolower(preg_replace('/[^a-zA-Z0-9_-]+/', '- ', $string));
          猜你喜欢
          • 2020-08-29
          • 1970-01-01
          • 1970-01-01
          • 2016-05-17
          • 2011-02-13
          • 2014-11-02
          • 1970-01-01
          • 1970-01-01
          • 2020-12-23
          相关资源
          最近更新 更多