2015-12-27 30 views
2

我是Laravel的相对初学者(使用5.2.3版本),并且一直在通过Laracasts上的教程,然后做了一些我自己的实验。通过slu Search而不是编号搜索对象

我成功地建立了由它的ID从表中获取的项目的路径,如下图所示

Route::get('/wiseweasel/{id}', '[email protected]'); 

为了简单起见,控制器只需DD的文章

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

这工作绝对罚款 - 我访问eg/wiseweasel/2并获得id2记录的内容。

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

Route::get('/wiseweasel/{slug}', '[email protected]'); 

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

嵌塞第二条记录是“第二条”。所以,访问url/wiseweasel/secondarticle,我希望看到与以前dd'd相同的记录。相反,我最终得到null。

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

这让我怀疑这是否可能是一些奇怪的缓存问题?我试过

PHP工匠路线:明确

的情况下,路由是被缓存。我也尝试重新启动Apache和MySql(我正在使用XAMMP)。

尽管如此,我还是没有运气...不知道我是否误解了某些事情是如何工作或发生了什么...所以如果任何人有任何关于我可能做错了什么或任何尝试的建议,我会非常感谢! :)

回答

8

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

当您使用:

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

你告诉Laravel - 通过ID找到www_articles记录。 (不管你叫这个id $ slug)。

达到你想要改变什么:

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

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

这将这样的伎俩(对于slug把名字列在表中的数据库)。当然要记住,在这种情况下,slu should在所有记录中应该是唯一的,否则你将无法获得所有的slu。。

+0

感谢Marcin,这工作完美!这是有道理的,因为我猜laravel在这种情况下无法知道$ id或$ slug或任何方式,因为它只是通过url提供的任何东西的占位符。谢谢你的解释:) 当你说塞必须是独特的,如果我首先选择一个类别然后塞 - 这可能是在这种情况下塞必须是唯一的类别? (虽然这仍然是一个问题,如果试图访问没有我猜的类别) –

+0

我的意思是每个类别应该有独特的slu。。如果两个类别有相同的slu it,这将是一个问题,因为你不能确定你想得到什么类别的slu。。所以当填充新类别的slu you时,你需要确保它是唯一的 –

+0

好吧,我明白了,谢谢:)无论如何,它们应该始终是唯一的(通用的“第一篇”slu was仅用于测试!) –

0

如果你有这样的

Route::get('/wiseweasel/{id}', '[email protected]'); 
Route::get('/wiseweasel/{slug}', '[email protected]'); 

两条路线,它会永远使用第一个。显然,没有id'secondarticle',所以它返回null(尽管在这种情况下没有关系,它们都指向相同的方法)。

原因是路由会搜索可能的路由,直到找到匹配,这总是与{id}一致。为什么?你不告诉路由{id}必须匹配一个整数!

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

/wiseweasel/{id}/{slug?} 

另一项建议。不要使用xx_articles等名称作为模型,而应使用文章。这样你可以使用新的implicit route binding。因此,使用隐式路由绑定您的网址应该是这样的(假设你的模式被称为第二条)

Route::get('/wiseweasel/{article}', '[email protected]'); 
+0

谢谢Bojan - 我只有一条路线,因为我只是修改了“id”路线来创建“slug”路线。但是,这是一个需要牢记的地方,因为在你的例子中,两者基本上是相同的路线,就拉拉维尔而言! 我已经使用了ww_前缀,因为我可能有多个不同的文章表(包含网站不同区域的文章),所以模型匹配表名。还是使用非复数版本作为型号名称? –

+0

他们不应该是复数,不。另外,如果你有不同的类型,你可以用不同的方式处理,看看morphTo –

+0

看起来它可能会有用......我可能会回到它,一旦我必须更多地了解基础知识,但谢谢! :) –

7

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

使用新的隐式路由模型绑定,您可以告诉模型它应该用于路由绑定的密钥。

// routes 
Route::get('/wiseweasel/{article}', '[email protected]'); 


// Article model 
public function getRouteKeyName() 
{ 
    return 'slug'; 
} 

// controller 
public function singleArticle(Article $article) 
{ 
    dd($article); 
} 

Laravel Docs - Route Model Binding

+0

这很方便知道另一种方法,谢谢! :) –

4

也许这是一个有点晚了答案,但还有另一种方式继续使用find方法和使用为你的表标识。您必须在模型中将受保护的$ primaryKey属性设置为'slug'

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

这工作,因为find方法在内部使用从Model类的getQualifiedKeyName方法,它使用了$ PrimaryKey属性。

+0

这是我认为最好的解决方案。 – jfadich

+0

谢谢塞尔吉奥,知道这很有用!在这种情况下,我想我可能会保留ID作为主键,但在其他情况下,它会很方便地将其更改为其他字段:) (我的问题主要是由于不完全理解find方法Marcin的回答对我很好解释,但这也是一个很好的解决方案!) –

相关问题