我需要根据文章标题生成独特的slu ..为了匹配slugs,我想在末尾添加一个数字,使它们成为唯一的。我根据我找到的其他工作做了这个功能:
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 函数生成新的slugs,该函数将字符串转换为slug形式。然后我尝试从数据库中查询现有的slugs,按顺序排序(高>低)并且在有序集合中取得必要的最高值。 问题是MySQL当然会将它们命名为字符串,因此 slug-title-9 实际上会被认为高于 slug-title-10 ,因为它将它们排序为字符和不是基于最后数字的值。我怎样才能做到这一点?有没有办法根据最后一个数字订购它们,还是我走错了方向?
我想避免的解决方案:
我见过其他实现,人们一次查询所有simmilar slugs,计算它们然后将count + 1追加到新slug的末尾。 这很糟糕,因为如果删除一些文章,整体计数会降低,新的slug可能会与旧版本冲突。
我已经看到一个实现,其中一个人将1附加到slug的末尾并检查它是否存在。如果它存在,他们将改为附加2并尝试检查是否存在,直到找到例如 slug-title-9 ,这样就不存在了。 IMO这很糟糕,因为你给数据库带来了不必要的压力。
我需要一个不错的解决方案,因为我正在研究的项目经常会遇到匹配的slu ..
答案 0 :(得分:1)
lastInsertId返回id的每个连接,这意味着并发的sql连接不会相互干扰。
但是,对于你正在做的事情,lastInsertId()可能不是最好的方法。我看到你已经在使用Eloquent模型。在表中创建新条目时,这些模型会返回相应的对象,然后您可以准确获取该对象的ID而不会产生任何混淆。
$article = Article::create(['title' => 'First post', 'content' => '...']);
echo $article->id;
这将始终输出正确的文章ID,您不必担心实施细节。我无法看到在现代Web框架中使用lastInsertId的充分理由,除非是极少数边缘情况。
作为一般规则,尽量避免直接处理应用程序中的数据库并使用框架提供的抽象 - 它将使您的代码更易于维护和更易于理解。
P.S。这可能对你不重要,但lastInsertId()不适用于事务。