Search code examples
phplaravelcrudlaravel-11

Laravel CRUD application returning null for individual items


I am trying to make a Laravel crud application following a tutorial but unable to get my items to show with data individually. I can output all items in the database but unable to output a single item with postman. Hoping someone can help me figure this out, thank you.

In postman, this outputs all the data correctly http://localhost:8000/api/orders/

However, when I try to look at an individual item, it returns all null for any item ID http://localhost:8000/api/orders/1 results in null data http://localhost:8000/api/orders/2 results in null data http://localhost:8000/api/orders/3 results in null data etc

output postman http://localhost:8000/api/orders/

"data": [
        {
            "id": 3,
            "details": "CREDIT\n",
            "posting_date": "2023-10-05",
            "description": "Online Transfer from CHK ...8760 transaction#: 18639\n",
            "amount": "950.00",
            "type": "ACCT_XFER\n",
            "balance": "2468.81",
            "check_or_slip": "",
            "category": "Rent",
            "property": "",
            "notes": ""
        },
        {
            "id": 2,
            "details": "DEBIT\n",
            "posting_date": "2023-09-05",
            "description": "Online Transfer to CHK ...8760 transaction#: 18362 09/05\n",
            "amount": "-1050.00",
            "type": "ACCT_XFER\n",
            "balance": "1518.81",
            "check_or_slip": "",
            "category": "",
            "property": "",
            "notes": ""
        },
output postman http://localhost:8000/api/orders/3
{
    "data": {
        "id": null,
        "details": null,
        "posting_date": null,
        "description": null,
        "amount": null,
        "type": null,
        "balance": null,
        "check_or_slip": null,
        "category": null,
        "property": null,
        "notes": null
    }
}

I have 4 files which I have created with the tutorial but changed it to fit my use.

routes-> api.php
<?php

use App\Http\Controllers\Api\PurchaseOrdersController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\AuthController;



Route::post('/login', [AuthController::class, 'login']);
Route::post('/register', [AuthController::class, 'register']);

Route::middleware(['auth:sanctum'])->group(function () {

    Route::post('/logout', [AuthController::class, 'logout']);
    Route::get('/profile', [AuthController::class, 'profile']);
});

Route::apiResource('orders', PurchaseOrdersController::class);

Route::get('/user', function (Request $request) {
    return $request->user();
})->middleware('auth:sanctum');
Models -> Orders.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Orders extends Model
{
    use HasFactory;

    protected $table = 'accounting';

    protected $fillable =[
        'details',
        'posting_date',
        'description',
        'amount',
        'type',
        'balance',
        'check_or_slip',
        'category',
        'property',
        'notes'
    ];
}
Resources -> OrderResource.php
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class OrderResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'details' => $this->details,
            'posting_date' => $this->posting_date,
            'description' => $this->description,
            'amount' => $this->amount,
            'type' => $this->type,
            'balance' => $this->balance,
            'check_or_slip' => $this->check_or_slip,
            'category' => $this->category,
            'property' => $this->property,
            'notes' => $this->notes
        ];
    }
}

App->http->Controllers->Api->PurchaseOrdersController.php
<?php

namespace App\Http\Controllers\Api;

use App\Models\Orders;
use App\Http\Resources\OrderResource;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\Request;

class PurchaseOrdersController extends Controller
{
    public function index()
    {
        $orders = Orders::get();
        if ($orders->count() > 0) {
            return OrderResource::collection($orders);
        } else {
            return response()->json(['message' => 'No record available'], 200);
        }
    }

    //add to database
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'details' => 'required|string|max:255',
            'posting_date' => 'string|max:255',
            'description' => 'string|max:255',
            'amount' => 'decimal:2',
            'type' => 'string|max:255',
            'balance' => 'decimal:2',
            'check_or_slip' => 'string|max:255',
            'category' => 'string|max:255',
            'property' => 'string|max:255',
            'notes' => 'string|max:255',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'message' => 'All fields are mandatory',
                'error' => $validator->messages(),
            ], 422);
        }

        $orders = Orders::create([
            'details' => $request->details,
            'posting_date' => $request->posting_date,
            'description' => $request->description,
            'amount' => $request->amount,
            'type' => $request->type,
            'balance' => $request->balance,
            'check_or_slip' => $request->check_or_slip,
            'category' => $request->category,
            'property' => $request->property,
            'notes' => $request->notes
        ]);

        return response()->json([
            'message' => 'Purchase Order Created Successfully',
            'data' => new OrderResource($orders)
        ], 200);
    }
    //update database item
    public function update(Request $request, Orders $orders)
    {
        $validator = Validator::make($request->all(), [
            'details' => 'required|string|max:255',
            'posting_date' => 'string|max:255',
            'description' => 'string|max:255',
            'amount' => 'decimal:2',
            'type' => 'string|max:255',
            'balance' => 'decimal:2',
            'check_or_slip' => 'string|max:255',
            'category' => 'string|max:255',
            'property' => 'string|max:255',
            'notes' => 'string|max:255'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'message' => 'All fields are mandatory',
                'error' => $validator->messages(),
            ], 422);
        }

        $orders->update([
            'details' => $request->details,
            'posting_date' => $request->posting_date,
            'description' => $request->description,
            'amount' => $request->amount,
            'type' => $request->type,
            'balance' => $request->balance,
            'check_or_slip' => $request->check_or_slip,
            'category' => $request->category,
            'property' => $request->property,
            'notes' => $request->notes
        ]);

        return response()->json([
            'message' => 'Purchase Order Updated Successfully',
            'data' => new OrderResource($orders)
        ], 200);
    }
    //get from database
    public function show(Orders $orders)
    {
        return new OrderResource($orders);
    }
    //delete from database
    public function destroy(Orders $orders)
    {
        $orders->delete();
        return response()->json([
            'message' => 'Purchase Order Deleted Successfully',
            'data' => new OrderResource($orders)
        ], 200);
    }
}

I have tried using the update and delete on a single order item http://localhost:8000/api/orders/3 which returns success but no changes in the database guessing because single items are returning null.

{
    "details" : "test",
    "posting_date" : "2024-09-04 04:21:38",
    "description" : "test",
    "amount" : "25.00",
    "type" : "test",
    "balance" : "55.00",
    "check_or_slip" : "test",
    "category" : "test",
    "property" : "test",
    "notes" : "test"
}
 GET|HEAD        / .................................................................................................................................................................................... 
  POST            api/login ................................................................................................................................................... Api\AuthController@login  
  POST            api/logout ................................................................................................................................................. Api\AuthController@logout  
  GET|HEAD        api/orders ......................................................................................................................... orders.index › Api\PurchaseOrdersController@index  
  POST            api/orders ......................................................................................................................... orders.store › Api\PurchaseOrdersController@store  
  GET|HEAD        api/orders/{order} ................................................................................................................... orders.show › Api\PurchaseOrdersController@show  
  PUT|PATCH       api/orders/{order} ............................................................................................................... orders.update › Api\PurchaseOrdersController@update  
  DELETE          api/orders/{order} ............................................................................................................. orders.destroy › Api\PurchaseOrdersController@destroy  
  GET|HEAD        api/profile ............................................................................................................................................... Api\AuthController@profile  
  POST            api/register ............................................................................................................................................. Api\AuthController@register  
  GET|HEAD        api/user .............................................................................................................................................................................  
  GET|HEAD        sanctum/csrf-cookie ................................................................................................ sanctum.csrf-cookie › Laravel\Sanctum › CsrfCookieController@show  
  GET|HEAD        up ................................................................................................................................................................................... 

result of DD in the show function

App\Models\Orders {#1188 // app\Http\Controllers\Api\PurchaseOrdersController.php:110
  #connection: null
  #table: "accounting"
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  +preventsLazyLoading: false
  #perPage: 15
  +exists: false
  +wasRecentlyCreated: false
  #escapeWhenCastingToString: false
  #attributes: []
  #original: []
  #changes: []
  #casts: []
  #classCastCache: []
  #attributeCastCache: []
  #dateFormat: null
  #appends: []
  #dispatchesEvents: []
  #observables: []
  #relations: []
  #touches: []
  +timestamps: true
  +usesUniqueIds: false
  #hidden: []
  #visible: []
  #fillable: array:10 [
    0 => "details"
    1 => "posting_date"
    2 => "description"
    3 => "amount"
    4 => "type"
    5 => "balance"
    6 => "check_or_slip"
    7 => "category"
    8 => "property"
    9 => "notes"
  ]
  #guarded: array:1 [
    0 => "*"
  ]
}

Solution

  • Since you're doing implicit model binding, your type hinted variable has to match the URI parameter name. Based on your route definition:

    api/orders/{order}
    

    Your $orders variable in the show() method is not matching that, so model binding doesn't work here, and wont return any results.

    Change your method definition to this:

    public function show(Orders $order)
    {
        return new OrderResource($order);
    }
    

    You can read more here: https://laravel.com/docs/11.x/routing#implicit-binding