1

Looking in-depth in the official docs, I read about using apiResources to be more precise in routes definition for API controllers - especially if they don't include any HTML. That's my case.

I'm on a Laravel 5.6 project that uses AJAX to fetch data inside Vue components. Until today, I was using normal controllers - placed in /app/Http/Controllers and with Route::resources declared in /routes/web.php.

It were working fine until today, when I tried to refactor them as the docs sugests, like this:

/app/Http/Controllers/API/ItemController.php

<?php

// Definizione Namespace
// before: App\Http\Controllers;
namespace App\Http\Controllers\API;

use App\Item;
use Illuminate\Http\Request;
// Added after refactoring
use App\Http\Controllers\Controller;
use App\Http\Resources\Item as ItemResource;

class ItemController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return ItemResource::collection(Item::all());
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $item = new Item();

        $item->codice = $request->codice;
        $item->data_acquisto = $request->data_acquisto;
        $item->serial = $request->serial;
        $item->labeled = $request->labeled;
        $item->estensione_garanzia = $request->estensione_garanzia;
        $item->stato = $request->stato;
        $item->data_dismissione = $request->data_dismissione;
        $item->codice = $request->codice;

        $item->save();

        return response()->json([
            'success' => 'Item salvato'
        ]);
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Item  $item
     * @return \Illuminate\Http\Response
     */
    public function show(Item $item)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Item  $item
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Item $item)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Item  $item
     * @return \Illuminate\Http\Response
     */
    public function destroy(Item $item)
    {
        //
    }
}

/routes/api.php

// Default stuff
[...]

// Resources
Route::apiResources([
    'componente' => 'ComponenteController',
    'condizione' => 'CondizioneController',
    'fornitore' => 'FornitoreController',
    'gruppo' => 'GruppoController',
    'gruppoPermesso' => 'GruppoPermessoController',
    'componente' => 'ComponenteController',
    'item' => 'ItemController',
    'locazione' => 'LocazioneController',
    'permesso' => 'PermessoController',
    'tipologia' => 'TipologiaController',
    'utente' => 'UtenteController'
]);

Now on load (on GET/index()), I'm getting an exception without error message, thrown by this:

Symfony\Component\HttpKernel\Exception\NotFoundHttpException

Here's an extract of it:

enter image description here

I'm pretty new with Laravel. This is the very first project. Maybe am I missing something?

Thanks everyone in advance for help.

  • See this episode (free) https://laracasts.com/series/whats-new-in-laravel-5-5/episodes/20 – Kyslik Jul 23 '18 at 11:38
  • Thanks @kyslik for suggestion, but I didn't get my specific case. I think that it could be caused by moved controllers to API folder, but somehow the framework doesn't find them. –  Jul 23 '18 at 12:26
  • Check this links for troubleshooting the route errors like this https://stackoverflow.com/questions/15843265/laravel-4-exception-notfoundhttpexception – gil Jul 23 '18 at 13:07
  • 1
    API routes have default "api" prefix. Are you requesting to URL with api/index ... ? – Ts8060 Jul 24 '18 at 05:45
  • Many thanks @ts8060, that's the way. After that I just changed the path in ```RouterServiceProvider.php``` in order to point to the right path. See my answer below for details. –  Jul 24 '18 at 07:38

2 Answers2

0

Finally the issue is solved.

As suggested by @ts8060, I added the default /api prefix to my paths in AJAX calls. I.e.:

url: '/api/item' points to /app/Http/Controllers/API/ItemController (to index() method in this case).

I totally jumped the section in paragraph were API prefix being mentioned (for those who need it can be found here).

Additionally, as a Slack community user told me (credits: dadibom), I changed the path in /app/Http/Providers/RouteServiceProvider.php at line 17, in order to redirect the calls to the right destination (the ../Controllers/API folder):

From

protected $namespace = 'App\Http\Controllers';

to

protected $namespace = 'App\Http\Controllers\API';

That's it.

Thanks again to all for your precious help.

0

Just an add-on to your answer, as I was looking to solve a similar problem. Instead of changing the $namespace on line 17, have a look at the mapApiRoutes() and adjust the namespace there.

->namespace($this->namespace . "\API")

That will look for Controllers in the API/ subdirectory for routes in api.php

Other routes (ie in web.php) will keep their original namespace. That way you can still use regular non-api routing.

paratechX
  • 41
  • 1
  • 3
  • Thanks for suggestion @paratechx, I'll try this on the next project. –  Nov 23 '18 at 09:06