phplaravellaravel-5.8route-model-binding

Laravel won't resolve model


I'm building an application to track expenses, using laravel 5.8 as the back-end. When I try to access the show method on my controller, I find laravel is giving me a fresh instance of the model instead of fetching the one matching the id provided.

I tried checking the actual value that was taking from the URI, which was correct and also manually querying to see if it had any results, which it did. I also checked all names where written properly (checking plurals and singulars).

The index method with return Expense::all() works just fine.

The model is empty, it just has a $guarded attribute.

This is the routes file located at routes/api.php

Route::apiResource('expenses', 'ExpenseController');

This is the controller located at app/Http/Controllers/ExpenseController.php

namespace App\Http\Controllers;

use App\Models\Expense;

class ExpenseController extends Controller
{
    public function show(Expense $expense)
    {
        return Expense:findOrFail($expense->getKey()); // key is null since it's a fresh model
    }
}
public function show($expense)
{
    //dd($expense); //Shows the id given on the URI
    return Expense::where('id', $expense)->firstOrFail(); //Works!
}

Expense model

namespace App\Models;

use App\Model;

class Expense extends Model
{
    protected $guarded = [
        'id'
    ];
}

I'm expecting to get the JSON data of the model with the given id, but instead I'm getting a fresh model with $exists = false, not getting any 404 errors.

I'm also using laravel/telescope and it shows the request finished with a 200 code and no queries made.

Reponse when using dd

Expense {#378 ▼
  #guarded: array:1 [▶]
  #connection: null
  #table: null
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  #perPage: 15
  +exists: false
  +wasRecentlyCreated: false
  #attributes: []
  #original: []
  #changes: []
  #casts: []
  #dates: []
  #dateFormat: null
  #appends: []
  #dispatchesEvents: []
  #observables: []
  #relations: []
  #touches: []
  +timestamps: true
  #hidden: []
  #visible: []
  #fillable: []
}

This is the entire class app\Model.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model as BaseModel;

/**
 * Class Model
 * @package App
 * @method static static|null find($id)
 * @method static static findOrFail($id)
 * @method static static create(array $data)
 * @method static Collection all()
 */
class Model extends BaseModel
{

}

Fix: I was missing the web middleware in the RouteServiceProvider


Solution

  • Since I'm using the routes/api.php file for my routes, I needed to change the api middleware to the web one in the RouteServiceProvider file located inside app/Providers.

    Piece of code needed to be changed:

    /**
         * Define the "api" routes for the application.
         *
         * These routes are typically stateless.
         *
         * @return void
         */
        protected function mapApiRoutes()
        {
            Route::prefix('api')
                 //->middleware('api')
                 ->middleware('web')
                 ->namespace($this->namespace)
                 ->group(base_path('routes/api.php'));
        }