2015-12-27 37 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的回答對我很好解釋,但這也是一個很好的解決方案!) –

相關問題