【问题标题】:Laravel: Contract file is not instantiable while building ControllerLaravel:构建控制器时合同文件不可实例化
【发布时间】:2020-12-18 17:38:29
【问题描述】:

我正在尝试向我的 Laravel 应用程序添加购物车功能。我从 GitHub 安装了 darryldecode/laravelshoppingcart 包,并一直按照这两个网站的说明进行操作。

TECHPOOL-Create a Shopping Cart with Laravel 6

LARASHOUT-Laravel E-Commerce Application Development – Checkout

我能够使用第一个网站创建大部分购物车功能,但它不包括结帐和下订单,所以我找到了第二个网站。

问题是合同文件不起作用。这是我得到的错误。

Illuminate\Contracts\Container\BindingResolutionException 目标 [App\Contracts\OrderContract] 在构建 [App\Http\Controllers\CheckoutController] 时不可实例化。 http://localhost:8000/checkout

我在结帐过程中使用合同文件的地方在第二个网站中进行了说明。我对代码做了一些更改,以便与第一个网站保持一致,但我主要遵循网站所说的内容。

这是错误中提到的代码。

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()
    {
        //
    }
}

我对合约概念并不是很熟悉,因为我最近才开始学习 Laravel,我完全迷失了这里。也许问题是我没有创建另一个必要的文件或其他文件。

任何帮助将不胜感激,因为我尝试了多种方法都没有成功。

提前谢谢你。

【问题讨论】:

  • 当请求这个接口时,容器需要知道你想要什么实例......所以可能你缺少的部分......你需要在容器中为此设置绑定>

标签: laravel shopping-cart


【解决方案1】:

是的,这是意料之中的......你的合同应该指向一个 Solid 类,否则它会在尝试从容器中解决它时失败。所以这是你应该做的:

  1. 创建一个实现该特征的类。

  2. 转到您的 AppServiceProvider 并将其绑定到该合同,如下所示:

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-&gt;app-&gt;bind(\App\Contracts\OrderContract::class, App\Repositories\ClassImplementingOrderContract::class);,所以你要创建的类看起来像这样class ClassImplementingOrderContract implements OrderContract {}
  • 嘿,当我创建 OrderContract.php 文件时,我还创建了 OrderRepository.php 文件 RepsitoryServiceProvider.php 文件(我将在我的问题中添加代码)。我认为我对 RepsitorySeviceProvider.php 文件所做的就是您在建议 2 中的意思。但我不确定第 1 条建议。这是关于 OrderRepository.php 文件吗?非常感谢您帮助我。
  • 将代码添加到您的问题中,并确保您在其他 Laravel 中注册了 RepsitorySeviceProvider.
  • 我认为我还没有注册 RepsitoryServiceProvider.php。也许这就是问题所在......你能告诉我我应该找到哪个文件来执行此操作吗?
  • 有办法做到这一点。首先是通过您的config/app.php 文件,向下滚动到177 行并将其放在其他服务提供商的正下方。或者您可以像这样在 AppServiceProvider 的 register 方法中注册它:$this-&gt;register(RepsitorySeviceProvider::class);。选择你觉得自然的。
猜你喜欢
  • 2023-03-05
  • 2015-01-08
  • 2019-07-05
  • 2018-11-28
  • 1970-01-01
  • 2017-07-24
  • 2021-04-13
  • 2016-07-05
  • 1970-01-01
相关资源
最近更新 更多