【问题标题】:Laravel - How to properly generate unique slugs from article titles?Laravel - 如何从文章标题中正确生成独特的 slug?
【发布时间】:2016-06-16 12:58:28
【问题描述】:

我需要根据文章标题生成独特的 slug。对于匹配的蛞蝓,我想在末尾附加一个数字以使它们独一无二。我根据我发现的其他工作制作了这个函数:

static function slugify($title)
    {
        $slug = str_slug($title, '-');
        //THIS IS THE PROBLEMATIC LINE:
        $common = Article::whereRaw("slug RLIKE '^{$slug}(-[0-9]+)?$'")->orderBy('slug', 'desc')->get();
        $count = count($common);
        if( $count > 0 ){
                    $last = $common[0];
                    $broken = explode('-', $last->slug);
                    $num = $broken[count($broken)-1];
                    $num = intval($num) + 1;
                    return $slug.'-'.$num;
        } else
            return $slug.'-1';
    }

问题: 如您所见,我尝试使用 Laravel 的 str_slug 函数生成新的 slug,该函数会将字符串转换为 slug 形式。然后我尝试从数据库中查询现有的 slug,将它们降序排列(高 > 低),并在有序集中取最高的。 问题是 MySQL 当然将它们排序为字符串,因此 slug-title-9 实际上会被认为高于 slug-title-10 因为它将它们作为字符排序并且不是基于最后数字的值。我怎样才能使这项工作?有没有办法根据最后一个数字来订购它们,还是我走错了方向?

我想避免的解决方案:

我见过其他实现,人们一次查询所有类似的 slug,计算它们,然后将 count+1 附加到新 slug 的末尾。 这很糟糕,因为如果你删除一些文章,总数量会减少,新的 sl 可能会与旧的冲突。

我见过一个实现,一个人将 1 附加到 slug 的末尾并检查它是否存在。如果它存在,他们将改为追加 2 并尝试检查它是否存在,等等,直到他们找到例如不存在的 slug-title-9IMO 这很糟糕,因为您给数据库带来了不必要的压力。

我需要一个体面的解决方案,因为我正在从事的项目有可能经常遇到匹配的 slug。

【问题讨论】:

  • 为什么不能简单地附加文章 ID?它保证是独一无二的,不会让您头疼。
  • @TadasPaplauskas 哇......因为我没想到......谢谢:)
  • @TadasPaplauskas 你能帮我理解一下吗?当我调用诸如 PDO::lastInsertId 之类的东西时,它会返回在此会话中插入的最后一个 id 吗?因此,例如,如果两个用户同时调用一个函数来插入一行,那么它就不会返回错误的 id,对吧?

标签: php mysql laravel


【解决方案1】:

lastInsertId 返回 id 的 per-connection,意味着并发 sql 连接不会相互干扰。

但是,无论您在做什么,lastInsertId() 都可能不是最好的方法。我看到你已经在使用 Eloquent 模型了。在 table 中创建新条目时,这些模型返回相应的 object,然后您可以准确地获取该 object 的 id,而不会造成任何混淆。

$article = Article::create(['title' => 'First post', 'content' => '...']);
echo $article->id;

这将始终输出正确的文章 ID,您不必担心实现细节。我看不出在现代 Web 框架中使用 lastInsertId 的充分理由,除了极少数情况。

作为一般规则,尽量避免在您的应用程序中直接处理数据库,并使用框架提供的抽象——这将使您的代码更易于维护和理解。

附:这对您来说可能并不重要,但 lastInsertId() 不适用于事务。

【讨论】:

    猜你喜欢
    • 2012-08-02
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    • 2021-01-30
    • 2019-07-10
    • 2017-06-01
    • 2020-09-28
    相关资源
    最近更新 更多