0

I have an interface that I wish to resolve on controllers. On registration inside a service provider, I am binding a class to the Service on condition.

Here is my service interface and two classes.

PaymentService::class


namespace App\Services\Payment\Contracts;

use App\Models\ParkingBill;

interface PaymentService
{
    
    public function request(ParkingBill $parkingBill, string $client): bool;

    public function confirm(ParkingBill $parkingBill, string $client): bool;
}

MpesaPaymentService::class

namespace App\Services\Payment;

use App\Models\ParkingBill;
use App\Models\PaymentMethod;
use App\Services\Payment\Contracts\PaymentService;

class MPesaPaymentService implements PaymentService
{

    private PaymentMethod $paymentMethod;

    public function __construct(PaymentMethod $paymentMethod)
    {
        $this->paymentMethod = $paymentMethod;
    }

    public function request(ParkingBill $parkingBill, string $client): bool
    {
        return true;
    }

    public function confirm(ParkingBill $parkingBill, string $client): bool
    {
        return false;
    }
}

AirtelPaymentService::class

namespace App\Services\Payment;

use App\Models\ParkingBill;
use App\Models\PaymentMethod;
use App\Services\Payment\Contracts\PaymentService;

class AirtelMoneyPaymentService implements PaymentService
{

    private PaymentMethod $paymentMethod;

    public function __construct(PaymentMethod $paymentMethod)
    {
        $this->paymentMethod = $paymentMethod;
    }

    public function request(ParkingBill $parkingBill, string $client): bool
    {
        return true;
    }

    public function confirm(ParkingBill $parkingBill, string $client): bool
    {
        return false;
    }
}

Here is the register method of PaymentServiceProvider where am binding the class

       $this->app->bind(PaymentService::class, function ($app) {

           PaymentMethod::query()
                ->where('id', request()->input('payment_method'))
                ->first();
            
            if ($paymentMethod->type == 'mpesa') {
                return new MPesaPaymentService($paymentMethod);
            } elseif ($paymentMethod->type == 'airtel') {
                return new AirtelMoneyPaymentService($paymentMethod);
            } else {
                return null;
            }

        });

I have also added the provider to the list of providers inside the app.php config file.


'providers' => [
    //...
   
        \App\Providers\PaymentServiceProvider::class,

    //...
]

Then this is where am trying to type hint it inside the controller method and access it inside the controller.

public function store(PaymentService $paymentService, Request $request, ParkingBill $parkingBill){

   //...

    return $paymentService->request($parkingBill, $request->payment_client);

}

I expect to get true or false based on the payment method I submit but am actually getting an exception.

Here is the exception

{
    "message": "Target [App\\Services\\Payment\\Contracts\\PaymentService] is not instantiable.",
    "exception": "Illuminate\\Contracts\\Container\\BindingResolutionException",
    "file": "C:\\wamp64\\www\\my-valet\\vendor\\laravel\\framework\\src\\Illuminate\\Container\\Container.php",
    "line": 1087,
    "trace": [...]

I have tried to remove the conditional binding but it is still not behaving, what could I be doing wrong?

I am using php V8.1.0 and Laravel V9

0

1 Answer 1

1

PaymentMethod query

$paymentMethod = PaymentMethod::find(request()->input('payment_method'));

Or,

$paymentMethod = PaymentMethod::query()
                ->where('id', request()->input('payment_method'))
                ->first();
Sign up to request clarification or add additional context in comments.

2 Comments

this is not working, even when I remove the conditional binding return only MPesaPaymentService (removed constructor parameters) it is saying the same thing.
I will mark this as answer because it has resolved itself even when I rivert it to $paymentMethod = PaymentMethod::query()->find(request()->input('payment_method'))->first() it is working okay.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.