web-dev-qa-db-ja.com

idではなくslugでオブジェクトを検索する

私はLaravel(バージョン5.2.3を使用))の比較的初心者であり、Laracastのチュートリアルに取り組んだ後、少し自分自身の実験を行っています。

以下のように、IDでテーブルからアイテムを取得するルートを正常に設定しました

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

簡単にするために、コントローラーは記事をddするだけです

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

これはまったく問題なく動作します。たとえば、/ wiseweasel/2にアクセスして、id2でレコードのコンテンツを取得します。

そこで、IDの代わりにレコードのslugフィールドを使用したいと思いました。 IDメソッドが機能していることがわかっているので、このルートとコントローラーを変更しようとしました(新しく作成したり、どちらも機能しなかったりしました)。

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

そして

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

2番目のレコードのスラッグは「secondarticle」です。したがって、URL/wiseweasel/secondarticleにアクセスすると、以前に削除されたのと同じレコードが表示されると思います。代わりに、私はnullになります。

さらに奇妙なことに、元のIDルート(/ wiseweasel/2)を使用してもレコードが返されます...これのすべてのトレースをルートとコントローラーから削除すると、これが失敗すると予想されます...

これは、これが奇妙なキャッシュの問題であるのではないかと思っています。私はもう試した

php artisan route:clear

ルートがキャッシュされている場合。また、ApacheとMySqlの両方を再起動してみました(両方にXAMMPを使用しています)。

それでもまだ運がない...何かがどう機能しているか、何が起こっているのかを誤解しているかどうかわからない...だから誰かが私が間違ったことをしたかもしれないことや何かしようとすることについて何か提案があれば、私はとても感謝しています! :)

11
Roxy Walsh

Laravelはslugの場合、レコードを別の方法で検索する必要があることを自動的に認識しません。

使用している場合:

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

Laravel-www_articlesのレコードをIDで検索します(このIDを$ slugと呼びます)。

変更したいものを実現するには:

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

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

これはトリックを実行します(slugの場合、データベースのテーブルに列の名前を入れます)。もちろん、この場合、スラッグはすべてのレコードで一意である必要があります。そうしないと、すべてのスラッグを取得できなくなります。

10

また、ルートモデルバインディングを使用してこれを処理し、解決されたインスタンスをメソッドに注入するオプションもあります。

新しい暗黙のルートモデルバインディングを使用すると、ルートバインディングに使用するキーをモデルに伝えることができます。

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


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

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

Laravel Docs-Route Model Binding

34
lagbox

多分それは答えに少し遅れますが、findメソッドを使い続け、テーブル識別子としてslugを使用する別の方法があります。保護された$ primaryKeyプロパティを 'slug'に設定する必要がありますあなたのモデル。

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

find メソッドは$ primaryKeyプロパティを使用するModelクラスの getQualifiedKeyName メソッドを内部的に使用するため、これは機能します。

SCOPEを使いやすく、簡単で便利です。

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

これで、次のように使用できます。

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

グローバルスコープの適用

0
Abbas Arif

このようなルートが両方ある場合

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

常に最初のものを使用します。明らかに、「secondarticle」というIDはないため、nullを返します(ただし、この場合は問題ではありませんが、どちらも同じメソッドを指しています)。

その理由は、一致するルートが見つかるまで、ルートが可能なルートを検索するためです。これは常に{id}を持つルートです。どうして? {id}が整数と一致する必要があることをRouteに伝えていません!

{id}が整数として理解されていることを確認できますが、このようなURLを使用することをお勧めします

/wiseweasel/{id}/{slug?}

別の提案。モデルにはxx_articlesなどの名前を使用しないでください。代わりにArticleを使用してください。このようにして、新しい 暗黙のルートバインディング を使用できます。したがって、暗黙のルートバインディングを使用すると、URLは次のようになります(モデルがArticleであると想定)

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