Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

dsmI's avatar
Level 3

Routes and fetching data by name, instead of id

Hi there, today I decided to move my app from vanilla php to Laravel and since I'm new to the framework I was having already some troubles with.

The app that I'd build is an dictionary. Already set some models and controllers, but actually don't understand the part of the routing that much. In my vanilla php app I have for example dictionary/english/{name}. From the controller that I managed to get working I only view dictionary/{id}.

Is it possible to add the language between the dictionary and the word name in the url and do I need a controller for that or just a simple route modification? I'm using Route::resources for viewing the routes btw. The languages are selected form the form when creating a new word and are stored in the database as language.

And, is it possible to fetch the words by name and not by id, but still creating, storing, updating and deleting by id?

Thank you for your time.

Cheers :)!

0 likes
6 replies
shez1983's avatar
shez1983
Best Answer
Level 23

you will need to do in your routes.php something like

Route::get('dictionary/{language}/{name}',  'SomeController@index');

if you offer more than one language.. otherwise

Route::get('dictionary/english/{name}',  'SomeController@index');

you do need a controller but can also do it in the routes file (former is recommended)

and you can fetch words by name..

1 like
dsmI's avatar
Level 3

Okay, so if I understand you correct, I'll be needing a new controller for fetching only the languages and that may be only for the method index and show, without the others (create, store, update and destroy)? Do I need also middlewares and models for that too?

Last, how can I manipulate the id fetching so that I can view them by name?

Here is what I have for the id.

public function show($id)
{
    $data = [
        'word' => Word::findOrFail($id)
    ];
    return view('page.show')->with($data);
}
        

Does it need to be like that?

public function show($name)
{
    $data = [
        'word' => Word::findOrFail($name)
    ];
    return view('page.show')->with($data);
}
        

Thank you kindly :)

shez1983's avatar

i am not sure what you are asking for.. for example

Route::get('dictionary/{language}/{name}',  'SomeController@index');
function index($language, $name)
{
   // check what language is incoming & then get the name or whatever needs to be done
}


for this you could do it two ways you could change it so

Route::get('dictionary/english/{name}', 'EnglishController@index'); Route::get('dictionary/french/{name}', 'FrenchController@index');

here you already know the language so the index will just do whatever needs to be done for the {name} part  (but this will be more ugly ie repeating things)

for CRUD/Edit etc

you can do the same thing 

Route::post('dictionary/{language}/{name}', 'SomeController@update');


logic is the same as above example.. 

dsmI's avatar
Level 3

Yeah, I'd made it work finally the way I want it.

shez1983's avatar

i am not sure what this is:

  $toFindLang = isset($_GET[$language]);
    if ($toFindLang === $language) {

this seems wrong... you are in essence checking TRUE with the actual language (english etc)

i have no idea about your models/db structure so i cannot fix this but i imagine you have something like:

languages (id, name)
words(id, language_id, word)



(but i am not sure what your route domain/{language}/{word} is supposed to do.. r u doing a translation? synonymn.. once u let me know i can help better)

dsmI's avatar
Level 3

I'd revert the logic and because of that I deleted the previous edit. You can delete yours too cause it's not referring to a question at this moment.

So I followed your logic and wrote this route:

Route::get('dictionary/{language}/{id}', 'WordController@show');

which I assign to the existing controller rather than creating a new one.

I also managed to get the language in between the dictionary and the id. See code below.

Controller

public function show($language, $id)
{
    $word = Word::query()->findOrFail($id);
    $lang = Word::getLang($id, $language);
    return view('word.show', compact('word', 'lang', $word, $lang));
}

Model

public static function getLang($id, $language)
{
    // Finds the language belonging to the word by id from the database.
    $toFindLang = static::query()->select('language')->where([
        [
           'id',
            $id
        ],
        [
           'language',
            $language
        ]
    ])->value('language');

    // Checks if the language in the URL doesn't match the language
    // belonging to the word by id from database, if so redirects back to previous page.
    if ($language !== $toFindLang) {
        return redirect()->back();
    }
}

Basically what I'm trying to do is simply to check if the language in the url does not match the one associated with the id. This to prevent people from changing the url.

Also, is it better to split the route property in separate controller or will this do the job?

Thank you!

Please or to participate in this conversation.