2015-12-27 3 views
2

Я относительный новичок с Laravel (с использованием версии 5.2.3) и работал над учебниками по Laracasts, а затем выполнял немного своих собственных экспериментов.Поиск объекта по slug, а не по id

Я успешно создан маршрут, который извлекает элемент из таблицы по идентификатору, как показано ниже

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

Для простоты, контроллер просто д.Д. статья

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

Это работает абсолютно отлично - я нахожу eg/wiseweasel/2 и получаю содержимое записи с id2.

Итак, я тогда хотел использовать поле слизня из записи вместо id. Так как я знаю метод ID работал, я пытался просто модифицировать этот маршрут и контроллер (также пытался создать заново, и не работал) Так что теперь у меня есть:

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

и

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

слизняк для второй записи - «secondarticle». Поэтому, посетив url/wiseweasel/secondarticle, я ожидаю увидеть ту же запись, что и раньше. Вместо этого я заканчиваю нулевым.

Еще более странно, используя исходный маршрут id (/ wiseweasel/2), все еще возвращает запись ... когда я удалил все следы этого из маршрутов и контроллера, поэтому я ожидал бы, что это сбой ...

Это заставляет меня задаться вопросом, может ли это быть какая-то странная проблема кеширования? Я попытался

PHP мастерового маршрут: четкий

в случае маршрут кэшируется. Я также попытался перезапустить Apache и MySql (я использую XAMMP для обоих).

По-прежнему не везет, хотя ... не уверен, что я неправильно понял, как что-то работает или что происходит ... так что, если у кого-то есть какие-то предложения относительно того, что я мог сделать неправильно или что-нибудь попробовать, я бы будьте очень благодарны! :)

ответ

8

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 поставить имя столбца в таблице в базе данных). Конечно, помните, что в этом случае слизень должен быть уникальным во всех записях или вы не сможете получить все слизняки.

+0

Спасибо Marcin, что сработало отлично! Это имеет смысл, так как я полагаю, что laravel не знает, что означает $ id или $ slug или что-то в этом случае, поскольку это просто местозаполнитель для того, что подается через URL-адрес. Спасибо за ваше объяснение тоже :) Когда вы говорите, что слизень должен быть уникальным, было бы так, если бы я сначала выбрал категорию, а затем и слизню - предположительно, в этом случае слизь просто должна была быть уникальной в категория? (хотя это все равно будет проблемой, если когда-либо попытаться получить доступ без какой-либо категории, я думаю) –

+0

Я имею в виду, что каждая категория должна иметь уникальный слизень.Если у 2 категорий будет одинаковый слиз, это будет проблемой, потому что вы не сможете определить, какую категорию вы хотите получить, просто пробивая. Поэтому при заполнении пули для новой категории вам нужно убедиться, что она уникальна. –

+0

Хорошо, я понимаю, спасибо :) Они всегда должны быть уникальными в любом случае (общий «пуля» первой статьи была просто для тестирования!) –

0

Если у вас есть оба маршрута, как этот

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

он всегда будет использовать первый. Очевидно, что нет id 'secondarticle', поэтому он возвращает null (хотя в этом случае это не имеет значения, оба они указывают на тот же метод).

Причина заключается в том, что маршрут будет искать возможные маршруты до тех пор, пока не найдет соответствие, которое всегда совпадает с {id}. Зачем? Вы не говорите Маршруту, что {id} должен соответствовать целому числу!

Вы можете убедиться, что {ID} понимается как целое число, но я предлагаю использовать URLs, как это лучший вариант

/wiseweasel/{id}/{slug?} 

Другое предложение. Не используйте имена, такие как xx_articles для модели, но вместо статьи. Таким образом, вы можете использовать новый implicit route binding.Таким образом, используя неявный маршрут связывающего свой адрес будет выглядеть следующим образом (предполагается, что модель называется статьей)

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

Спасибо Bojan - У меня был только один маршрут, так как я просто изменил маршрут «id», чтобы создать маршрут «slug». Но это хороший момент, чтобы иметь в виду, поскольку два в вашем примере - это в основном тот же маршрут, что касается laravel! Я использовал префикс 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

Может быть, это немного поздно для ответа, но есть еще один способ сохранить с помощью метода поиска и использования слизняка как ваш идентификатор таблицы. Вам необходимо установить защищенный $ primaryKey на 'slug' в вашей модели.

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

Это будет работать, потому что find метод внутренне использует getQualifiedKeyName метод из класса модели, которая использует свойство $ PrimaryKey.

+0

Это лучшее решение, на мой взгляд. – jfadich

+0

Спасибо Серхио, это полезно знать! В этом случае я думаю, что, скорее всего, я сохраню идентификатор в качестве первичного ключа, но в других случаях было бы удобно изменить его на какое-то другое поле :) (моя проблема была прежде всего результатом не полного понимания метода find Ответ Марцина объяснил мне это хорошо, но это тоже могло быть хорошим решением!) –

 Смежные вопросы

  • Нет связанных вопросов^_^