'Laravel: Contract file is not instantiable while building Controller

I am trying to add a shopping cart function to my Laravel application. I installed darryldecode/laravelshoppingcart package from GitHub and have been following instructions in these two websites.

TECHPOOL-Create a Shopping Cart with Laravel 6

LARASHOUT-Laravel E-Commerce Application Development – Checkout

I was able to create most of the shopping cart function with the first website but it didn't cover checkouts and placing orders so I found the second website.

The problem is that the contract file is not working. Here is the error I got.

Illuminate\Contracts\Container\BindingResolutionException Target [App\Contracts\OrderContract] is not instantiable while building [App\Http\Controllers\CheckoutController]. http://localhost:8000/checkout

Where I use the contract file is in the checkout process witch is explained in the second website. I made few changes in the codes so that it will be consistent with the first website but mostly I followed what the website says.

Here are the codes that are mentioned in the error.

OrderContract.php

<?php

namespace App\Contracts;

interface OrderContract
{
    public function storeOrderDetails($params);
}

CheckoutController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Contracts\OrderContract;
use App\Http\Controllers\Controller;


class CheckoutController extends Controller
{
    protected $orderRepository;

    public function __construct(OrderContract $orderRepository)
    {
        $this->orderRepository = $orderRepository;
    }

    public function getCheckout()
    {
        return view('checkout');
    }

    public function placeOrder(Request $request)
    {
        // Before storing the order we should implement the
        // request validation which I leave it to you
        $order = $this->orderRepository->storeOrderDetails($request->all());

        dd($order);
    }
}

OrderRepository.php

<?php

namespace App\Repositories;

use Cart;
use App\Models\Order;
use App\Product;
use App\Models\OrderItem;
use App\Contracts\OrderContract;

class OrderRepository extends BaseRepository implements OrderContract
{
    public function __construct(Order $model)
    {
        parent::__construct($model);
        $this->model = $model;
    }

    public function storeOrderDetails($params)
    {
        $order = Order::create([
            'order_number'      =>  'ORD-' . strtoupper(uniqid()),
            'status'            =>  'pending',
            'grand_total'       =>  Cart::getSubTotal(),
            'item_count'        =>  Cart::getTotalQuantity(),
            'table_number'      =>  $params['table_number'],
            'name'              =>  $params['name'],
            'notes'             =>  $params['notes']
        ]);

        if ($order) {

            $items = Cart::getContent();

            foreach ($items as $item) {
                // A better way will be to bring the product id with the cart items
                // you can explore the package documentation to send product id with the cart
                $product = Product::where('name', $item->name)->first();

                $orderItem = new OrderItem([
                    'product_id'    =>  $product->id,
                    'quantity'      =>  $item->quantity,
                    'price'         =>  $item->getPriceSum()
                ]);

                $order->items()->save($orderItem);
            }
        }

        return $order;
    }
}

RepositoryServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Contracts\OrderContract;
use App\Repositories\OrderRepository;

class RepositoryServiceProvider extends ServiceProvider
{
    protected $repositories = [
        OrderContract::class            =>          OrderRepository::class,
    ];

    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        foreach ($this->repositories as $interface => $implementation) {
            $this->app->bind($interface, $implementation);
        }
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

I'm not really familiar with the contract concept since I only started learning Laravel recently and I'm completely lost here. Maybe the problem is that I haven't created another file that is necessary or maybe something else.

Any help would be appreciated as I have tried multiple methods with no success.

Thank you in advance.



Solution 1:[1]

Yes, this is expected...your contract should point to a Solid class else it's going to fail while trying to resolve it out of the container. So this is what you should do:

  1. Create a class that implements that trait.

  2. Go to your AppServiceProvider and bind it to that contract like this:

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
        $this->app->bind(\App\Contracts\OrderContract::class, App\Repositories\ClassImplementingOrderContract::class);
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

this should fix your problem.

Solution 2:[2]

This error could caused even if you have forget to add "RepositoryServiceProvider" into "config/app.php" 's serviceProviders array.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 gondolas