< GDB >'s avatar

Laravel 8 Routing - Not sure what I did wrong

It seems that in Laravel 8 you'll need to give the full path to the controller, and in previous versions that was not the case / well it was but it was done by an auto added namespace for said controller.

If I understand correctly there are 2 ways :

Just to be sure, this is the old way as I understood :

Route::get('/articles/{article}', 'ArticlesController@show')

NEW WAY =

PHP Syntax, which would leave me with :

Route::get('/articles', [ArticlesController::class, 'show']);

and String Syntax, which would leave me with :

Route::get('/articles', ['App\Http\Controllers\ArticlesController@show']);

Unfortunately, the PHP Syntax gives me an error : (example.com/articles)

Target class [ArticlesController] does not exist.

Unfortunately, the String Syntax gives me an error as well : (example.com/articles)

function () does not exist.

My 'ArticlesController.php' script looks like this :

<?php
    namespace App\Http\Controllers;
    use DB;
    use App\Models\Article;
    use Illuminate\Http\Request;

    class ArticlesController extends Controller
        {
          public function show($id){
          $article = Article::find($id);
         return view('articles.show', ['article'=>$article]);
		}
}

I thought maybe the error came because I'm searching for an id in the url but when i go to fex example.com/articles/1 i get a 404.

So by now it's clear that I misunderstood something, but after reading the docs and viewing some vids I'm not grasping what I'm doing wrong. Especially since both errors are different...

0 likes
8 replies
mrvbltzr's avatar
mrvbltzr
Best Answer
Level 10

If you use this:

Route::get('/articles', ['App\Http\Controllers\ArticlesController@show']);

Your action (2nd parameter) should be string and not array. Also, the variable name (in your controller's method parameters) should match with the wildcard in your URI, like this:

Route::get('/articles/{id}', 'App\Http\Controllers\ArticlesController@show');

Then your method:

public function show($id)
{
     $article = Article::findOrFail($id);
     return view('articles.show', compact('article'));
}

Also, I suggest you read this: https://laravel.com/docs/8.x/routing#route-model-binding

So you can do this easily:

Route::get('/articles/{article}', 'App\Http\Controllers\ArticlesController@show');

// or

// import
use App\Http\Controllers\ArticlesController;

// tuple route
Route::get('/articles/{article}', [ArticlesController::class, 'show']);

Then your method, like this:

public function show(Article $article)
{
     return view('articles.show', compact('article'));
}
2 likes
Thomasvdw's avatar

Hi @gillesdeb

In the case you are using the PHP syntax, did you import the controller at the top?

use App\Http\Controllers\ArticlesController;

If that does not work; can you test by chaging it to index instead of show (also remove $id in controller, and replace by a random id you know exists)?

1 like
< GDB >'s avatar

Hi @kygenz !

Thank you for the well written feedback, I tried the first way-of-action and indeed makes sense regarding the [ ] which put the path into an array.

Only changing my script to your example, I do not get the different database rows if i change the url example.com/articles/1 (first db row is always shown) seems that this is bc of the firstOrFAil() function (was there a specific reason you wrote this? > Assume you meant findOrFail() > in which case it would work as intended, thnx!)

The second way-of-action, I assume this is the least common choice? As the web.php script would have a lot of use 'path' for each different controller... Or am I seeing this wrong?

Thnx again for your help!

< GDB >'s avatar

HI @thomasvdw,

Yes I did, but my PHP syntax was missing the /{article} part, I thought that wasn't necessary anymore, but was mislead by another example.

Thnx for helping, really appreciated! KyGenz got me to understand it a bit better (and working with both way-of-actions). Will read a bit more on it and try to add some other routes to get the hang of it.

Do you have any preference for php or string syntax? Looks like php syntax will clutter up my script layout (if several controllers need to be added).

Thnx again!

1 like
mrvbltzr's avatar

@gillesdeb, I'm glad I helped you.

About the firstOrFail -- Sorry for my mistake. It should be findOrFail().

The Route Model Binding is the most common/preferred choice by other developers when it comes to route definition because this automatically injects the model instance directly to your routes. This also eliminates the use of findOrFail() in your controllers. Read: https://laravel.com/docs/8.x/routing#route-model-binding to see how it works.

Try it and see for yourself. I will definitely suggest to utilize and take advantage of model binding.

1 like
< GDB >'s avatar

@kygenz,

After a day of playing with it, I prefer the PHP Syntax, it looks cleaner and as Thomas said I can consult the definition immediately. Which is nice, still learning a lot.

Stored your link yesterday already, but will need to read it a few times ;-)

Thnx again, cheers!

1 like

Please or to participate in this conversation.