Home  >  Q&A  >  body text

In-depth exploration of how to use interfaces/contracts in Laravel

Trying to increase my PHP/Laravel knowledge, so when creating new functionality I try to work with interfaces.

To set the scene: Our company has changed direct debit providers several times over the course of a year and I wanted to create this interface to make future changes more "scaffolded".

My code structure:

Application\Interface\DirectDebitInterface

interface DirectDebitInterface {
    public function createAccount($account);
    // additional methods
}

Application\Service\DirectDebit\Clients\Bottomline

class Bottomline implements DirectDebitInterface {
    public function getAccount(String $reference)
    {
        // do external API call, return back data
    }
}

App\Providers\AppServiceProvider @register

$this->app->bind(
    DirectDebitInterface::class,
    config('services.direct_debit_clients.' . // Bottomline
    config('services.direct_debit_clients.default') . '.class') // App\Services\DirectDebit\Clients\Bottomline::class
);

My current usage is valid but doesn't feel right, here is a test endpoint using the getAccount() method:

public function getAccount(DirectDebitInterface $directDebitInterface)
{
    dd($directDebitInterface->getAccount('OS10129676'));
}

My first question is, I've never seen anyone use an interface in a class's variable settings?

My second question is, I'm using Livewire to load the data but can't figure out how to use the interface.

Here is the sample code for my second question:

App\Http\Livewire\Example

public function mount(Account $account)
{
    self::getDirectDebitAccount();
}

private function getDirectDebitAccount(DirectDebitInterface $directDebitInterface)
{
    dd($directDebitInterface->getAccount($reference));
}

The above code fails because the method requires a parameter to be passed in, but I also cannot instantiate the class because it is an interface.

Aside from feeling like there are some fundamental gaps in my knowledge... It seems like I'm on the right track, but my usage of classes/interfaces is set up incorrectly.

Any suggestions on how to call this interface from inside a method or is it going wrong somewhere?

There,

P粉517090748P粉517090748219 days ago322

reply all(1)I'll reply

  • P粉615829742

    P粉6158297422024-02-18 11:23:42

    You are doing method-based dependency injection, which is perfectly valid but arguably less common than constructor-based dependency injection. Both have similar results, i.e. injecting the required dependencies, the main difference is the scope of the dependencies (method vs class).

    In a standard Laravel/PHP environment, constructor injection might look like this:

    private DirectDebitInterface $directDebitor;
    
    public function __construct(DirectDebitInterface $directDebitor)
    {
        $this->directDebitor = $directDebitor;
    }
    
    public function doSomething(string $account)
    {
        dd($this->directDebitor->getAccount($account));
    }

    Livewire is slightly different in that instead of using the __construct function in the Component, you need to use the mount() function.

    public function mount(DirectDebitInterface $directDebitor)
    {
        $this->directDebitor = $directDebitor;
    }

    Assuming you have correctly configured the service container in bindings, everything should work fine.

    reply
    0
  • Cancelreply