【问题标题】:Showing name in url instead of id?在 url 中显示名称而不是 id?
【发布时间】:2018-01-07 21:38:20
【问题描述】:

我正在 Laravel 中构建一个小应用程序,但我需要一些帮助。我读过类似的任务,但我认为它们与我所拥有的无关。

我正在构建的应用程序是一本字典,我真的不明白在 URL 中由 id 显示单词的部分。我尝试恢复凝乳的逻辑(store、update、delete、show),以便它们使用 word name 而不是 word id。那行得通。操作后重定向到路由 app/{name} 也有效。

现在,当凝乳没有对 id 采取行动时,我认为这不是它需要做的?

我也读过关于蛞蝓的文章,但由于我正在构建字典,不明白为什么我需要用 "-" 分隔单词?这是一个词,不像帖子。为什么我需要在表单中为 slug 提供一个额外的字段,因为 slug 必须等于 name?我在这里遇到一个错误:slug->unique() 字段不能为空。

如果有人有时间,请向我解释使 单词名称 显示在 URL 中的最佳方法是什么。谢谢你,我很感激。

编辑

这是我的更新 crud 代码:

public function update(UpdateWordRequest $request, $name)
{
    Word::query()->where('name', $name)->firstOrFail()->update($request->input());
    return redirect()->route('dictionary.show', ['name' => $name])->with('success', 'Edited successfully!');
}

它工作正常,但是当我重新编辑单词并将其更改为 word2 时,我会收到以下错误:尝试获取非对象的属性“名称”。

我需要做什么?谢谢你:)!

【问题讨论】:

  • 如果你所有的“名字”都是唯一的,那么使用名字作为 id 没有任何问题
  • 它们确实是独一无二的,但是当我添加例如 word1 和 word2 时,我得到一个错误:尝试获取非对象的属性。
  • 没有代码很难分辨 ;)
  • 给我们看一些代码
  • 稍后我会为您提供我的代码。我正在尝试修复此错误:App\Word::language 必须返回一个关系实例。不知道这里的问题可能出在哪里。几个小时前它确实起作用了。

标签: php laravel-5.5


【解决方案1】:

我认为你应该能够使用 trait 来解决这个问题。

我会创建一个特征调用 hasSlug 并具有以下代码:

<?php

namespace App\Traits;

trait HasSlug
{

protected static function bootHasSlug()
{
    static::creating(function ($model) {

        $columnName = static::getSlugColumn();

        $model->$columnName = str_slug($model->name); //convert your name to slug
    });
}


public function getSlugAttribute()
{
    $columnName = static::getSlugColumn();

    return (string) $this->attributes[$columnName];
}

protected static function getSlugColumn()
{
    if (isset(static::$slugColumn)) {
        return static::$slugColumn;
    }

    return 'slug';
}
}

所以现在,如果您每次创建记录时都对模型使用 HasSlug 特征,它会从您的模型中查找名称字段并从中创建一个 slug。

如果需要,请务必对您的姓名字段应用唯一约束。

要更强大,请查看 spatie slug 包https://github.com/spatie/laravel-sluggable

【讨论】:

  • 好的,但是碎屑呢。我是否需要类似“Word::query()-&gt;where('slug', $slug)-&gt;firstOrFail()...; 或 first() only”之类的东西。再说一次,迁移呢。是否需要 slug 字符串 必须是 unique(),我是否需要为 slug 字段添加表单?谢谢!
  • 首先添加一个迁移以创建 slug 字段。不,您不必在表单中有一个 slug 字段,因为您可以看到它会使用您的 name 字段并为其创建一个 slug,是的,您可以执行 Word::query()..... 或其他任何操作
  • 好吧,看起来没那么难。我会在我的 phpstorm 中尝试一下,看看它是否有效。另外,我认为变量$model 是我在我的显示视图中预测的,比如$words as $word?谢谢!
  • 模型就是你将使用的 HasSlug 特征。例如,如果您在 Word.php 中使用 HasSlug,则模型将为 $word,如果其他内容将是其他内容
  • Field 'slug' doesn't have a default value。是不是也需要nullable()?
【解决方案2】:

这是我最终想出的。

Word.php

我使用@usrNotFound 建议spatie/laravel-sluggable。

<?php

namespace App;

use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;

class Word extends Model
{
    use HasSlug;

    /**
    * @return SlugOptions
    */
    public function getSlugOptions(): SlugOptions
    {
        return SlugOptions::create()
            ->generateSlugsFrom('name')
            ->saveSlugsTo('slug')
            ->slugsShouldBeNoLongerThan(20);
    }

    /**
    * @param $query
    * @param $slug
    * @return mixed
    */
    public function scopeFindBySlug($query, $slug)
    {
        return $query->where('slug', $slug)
            ->get();
    }
}

WordController.php

<?php

namespace App\Http\Controllers;

use App\Word;
use App\Http\Requests\CreateWordRequest;
use App\Http\Requests\UpdateWordRequest;

class WordController extends Controller
{

    /**
     * Store a newly created resource in storage.
     * @param CreateWordRequest $request
     * @return mixed
     */
    public function store(CreateWordRequest $request)
    {
        $word = Word::query()
            ->create($request->input());
        return redirect()
            ->route('dictionary.show', $word->slug)
            ->with('success', 'Created successfully!');
    }

    /**
     * Display the specified resource.
     * @param $slug
     * @return mixed
     */
    public function show($slug)
    {
        $word = Word::whereSlug($slug)
            ->firstOrFail();
        return view('word.show')
            ->with('word', $word);
    }

    /**
    * Update the specified resource in storage.
    * @param UpdateWordRequest $request
    * @param $slug
    * @return mixed
    */
    public function update(UpdateWordRequest $request, $slug)
    {
        Word::whereSlug($slug)
            ->firstOrFail()
            ->update($request->input());
        return redirect()
            ->route('dictionary.show', $slug)
            ->with('success', 'Edited successfylly!');
    }

    /**
    * Remove the specified resource from storage.
    * @param $slug
    * @return mixed
    */
    public function destroy($slug)
    {
        Word::whereSlug($slug)
            ->delete();
        return redirect()
            ->route('dictionary.index')
            ->with('success', 'Deleted successfully');
    }
}

Route.php

Route::get('/dictionary/{slug}', 'WordController@show')
    ->name('dictionary.show')
    ->where('slug', '[-A-Za-z0-9_-]+');

创建、更新、销毁新词都可以正常工作。最终有一个小问题。当我想更新一个特定的单词并更改它的名称时,保存单词后,我得到了

抱歉,找不到您要查找的页面。

如果我查看 url,我会看到旧名称而不是新名称。 这与我的更新方法有关吗?我该如何解决它?

【讨论】:

    猜你喜欢
    • 2015-03-06
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 2017-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多