【问题标题】:Trying to make SEO friendly urls without using database尝试在不使用数据库的情况下制作 SEO 友好的网址
【发布时间】:2018-05-24 08:17:42
【问题描述】:

我正在构建我的第一个 Laravel 应用程序。我有属于不同类别的帖子。

我正在尝试为类别创建 SEO 友好的 URL /categories/category_name,而不在数据库中保存“slug”。

到目前为止,这是我带来的:

我的类别模型:

class Category extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }

    public function getSlugAttribute(): string
    {
        return str_slug($this->name);
    }

    public function getUrlAttribute(): string
    {
        return action('CategoriesController@index', [$this->id, $this->slug]);
    }
}

我的类别控制器

class CategoriesController extends Controller
{
    public function index($id, $slug = '')
    {
        $posts = Category::findOrFail($id)->posts;

        return view('index', compact('posts'));
    }
}

我的路线:

Route::get('/categories/{slug}', 'CategoriesController@index')->name('category');

使用{{ $post->category->url }} 我会得到类似http://localhost/category/1?alpha 的信息,但它可以工作并显示相应的帖子。路由返回错误。

我如何搭上id? 并使路线正常运行?

提前感谢您的帮助!

【问题讨论】:

  • 为什么不存储呢?无需每次都计算。

标签: php laravel laravel-5


【解决方案1】:

我假设您有一个人类可读的类别名称(例如 My Category),并且您正在将其转换为 URL 中的一个 slug(例如 my-category)。

这样做的一种天真的方法是尝试反转 slug 并按名称查找类别,但在某些用例中这不起作用。

class CategoriesController extends Controller
{
    public function index($slug)
    {
        $name = ucwords(str_replace('-', ' ', $slug));
        $posts = Category::where('name', '=', $name)->first()->posts;

        return view('index', compact('posts'));
    }
}

这种方法的问题是在将名称转换为 slug 时会丢失信息,例如,如果正确的类别名称包含连字符,则在转换生成的 slug 时连字符会变成空格。


您可以通过修改路线以不同的方式解决此问题,而无需存储 slug:

Route::get('/categories/{category}/{slug}', 'CategoriesController@index')->name('category');

在这种情况下,您在 URL 中同时传递 ID 和 slug。您可以从 ID 中获取类别,也可以使用路由模型绑定来自动获取它。这在技术上意味着您可以将任何字符串作为 slug 传递,它仍然可以工作。如果最终用户提供了不正确的 slug,您可以通过确定实际 slug 并重定向到规范 URL 来处理此问题。

class CategoriesController extends Controller
{
    public function index(Category $category, $slug)
    {
        if(str_slug($category->name) != $slug) {
            // Redirect to the canonical URL
        }

        $posts = $category->posts;

        return view('index', compact('posts'));
    }
}

在 URL 中同时保留 ID 和 slug 的好处是您可以免费获得重定向:如果类别名称更改,新 URL 将起作用,旧 URL 将自动重定向到新 URL。

旁注:如果您查看他的问题的 URL,您会注意到这是 StackOverflow 使用的方法。

【讨论】:

  • 谢谢!我最终使用这种方法(如 StackOverflow)来发布帖子并将 slugs 保存在数据库中的类别。
【解决方案2】:

我认为这是不可能的。背后的原因是您需要使用 slug 搜索类别但未存储在数据库中,因此您需要将 slug 转换为其原始值。

例如,如果您有一个名为“现代艺术”的类别,则 slug 看起来像 modern-art。如果您将该 slug 传递给您的控制器,则需要将其转换回“现代艺术”,以便能够通过其名称检索类别。但也许真正的名字是“现代艺术”或“现代艺术”!或者别的什么。

我建议您将 slug 存储在数据库中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-23
    • 2011-04-06
    • 2014-01-14
    • 2017-05-14
    • 2014-07-26
    • 2016-03-11
    • 2016-02-02
    • 2011-02-15
    相关资源
    最近更新 更多