按slug搜索对象而不是id

时间:2015-12-27 21:23:48

标签: laravel laravel-5 eloquent laravel-routing laravel-5.2

我是Laravel的相对初学者(使用版本5.2.3)并且一直在研究Laracasts的教程,然后做了一些我自己的实验。

我成功设置了一个路由,通过其ID从表中提取项目,如下所示

Route::get('/wiseweasel/{id}', 'WiseweaselController@singleArticle');

为简单起见,控制器只需阅读文章

public function singleArticle($id)
{
  $article = ww_articles::find($id);
  dd($article);
}

这非常正常 - 我访问eg / wiseweasel / 2并获取id2记录的内容。

因此,我想使用记录中的slug字段而不是id。既然我知道ID方法正在运行,我已经尝试过修改这条路线和控制器(也尝试重新创建,既没有工作)所以我现在有:

Route::get('/wiseweasel/{slug}', 'WiseweaselController@singleArticle');

public function singleArticle($slug)
{
  $article = ww_articles::find($slug);
  dd($article);
}

第二个记录的slu is是" secondarticle"。所以,访问url / wiseweasel / secondarticle,我希望看到与之前相同的记录dd' d out。相反,我最终得到了null。

更奇怪的是,使用原始的id路由(/ wiseweasel / 2)仍然会返回记录...当我从路由和控制器中删除了所有这些跟踪时,所以我希望这会失败... < / p>

这让我想知道这是否可能是一些奇怪的缓存问题?我试过了

php artisan route:clear

以防缓存路由。我也尝试重启Apache和MySql(我在两者中使用XAMMP)。

虽然仍然没有运气......不确定我是否误解了某些事情的作用或发生了什么......所以,如果有人对我可能做错了什么或任何事情有任何建议试试,我将非常感激! :)

5 个答案:

答案 0 :(得分:22)

您还可以选择使用路径模型绑定来处理此问题,并将已解析的实例注入您的方法。

使用新的隐式路径模型绑定,您可以告诉模型它应该用于路由绑定的哪个键。

    public function ScrollWithHero()
    {
        var stageW2:Number = stage.stageWidth/2;
        var stageH2:Number = stage.stageHeight/2;
        var view:Rectangle = new Rectangle(0,0,stage.stageWidth,stage.stageHeight);

        if(hero.x - stageW2 > 0)
        { 
            view.x = hero.x - stageW2; 

            if(hero.x + stageW2 > levelWidth)
            {
                view.x = levelWidth - stage.stageWidth;
            }
        }
        if(hero.y - stageH2 > 0)
        { 
            view.y = hero.y - stageH2; 

            if(hero.y + stageH2 > levelHeight)
            {
                view.y = levelHeight - stage.stageHeight;
            }
        }
        scrollRect = view;
    }

Laravel Docs - Route Model Binding

答案 1 :(得分:9)

Laravel不会自动知道slug它应该以不同的方式搜索记录。

使用时:

$article = ww_articles::find($slug);

你在告诉Laravel - 按身份查找www_articles的记录。 (不管你叫这个id $ slug)。

实现您想要改变的目标:

$article = ww_articles::find($slug);

$article = ww_articles::where('slug', $slug)->first();

这将解决问题(对于slug,将列的名称放在数据库的表中)。当然要记住,在这种情况下,slug在所有记录中应该是唯一的,否则你将无法获得所有的slu ..

答案 2 :(得分:6)

也许它的答案有点晚了,但还有另一种方法可以继续使用find方法并使用 slug 作为表标识符。您必须将受保护的 $ primaryKey 属性设置为模型中的&#39; slug&#39;

class ww_articles extends Model
{
    protected $primaryKey = 'slug';
    ...
}

这将起作用,因为find方法在内部使用Model类中使用$ primaryKey属性的getQualifiedKeyName方法。

答案 3 :(得分:0)

如果你有这样的路线

Route::get('/wiseweasel/{id}', 'WiseweaselController@singleArticle');
Route::get('/wiseweasel/{slug}', 'WiseweaselController@singleArticle');

它将始终使用第一个。显然,没有id'secondarticle',所以它返回null(虽然在这种情况下无关紧要,但它们都指向相同的方法)。

原因是路线将搜索可能的路线,直到找到匹配的地方,该地址始终是{id}的路线。为什么?你没有告诉路由{id}必须与整数匹配!

您可以确保{id}被理解为整数,但我建议使用这样的网址是更好的选择

/wiseweasel/{id}/{slug?}

另一个建议。不要将xx_articles等名称用于模型,而应使用Article。这样您就可以使用新的implicit route binding。因此,使用隐式路由绑定,您的网址将如下所示(假设您的模型称为文章)

Route::get('/wiseweasel/{article}', 'WiseweaselController@singleArticle');

答案 4 :(得分:0)

更好地使用SCOPE,轻松便捷。

public function scopeSlug($query, $slug)
{
    return $query->where("slug", $slug);
}

现在我们可以像这样使用它:

$article = ww_articles::slug($slug)->first();

Applying Global Scopes