Reputation: 467
I'm developing my own L5 package for handling payments. To be able to change the payment gateway in the future, I'm using interfaces.
My interface looks like this:
interface BillerInterface
{
public function payCash();
public function payCreditCard();
}
I also have a concrete implementation, which is the desired payment gateway.
class Paypal implements BillerInterface
{
public function payCash()
{
// Logic
}
public function payCreditCard()
{
// Logic
}
}
The Biller class is the main class, and the constructor method expects the above interface, like so:
class Biller {
protected $gateway;
public function __construct(BillerInterface $gateway)
{
$this->gateway = $gateway;
}
// Logic
}
Last, I created the service provider, to bind the interface to the gateway class.
public function register()
{
$this->app->bind(BillerInterface::class, 'Vendor\Biller\Gateways\Paypal');
}
Seems to be working, but I'm getting an error when trying to instantiate the Biller class...
Biller::__construct() must be an instance of Vendor\Biller\Contracts\BillerInterface, none given
I tried the following code but doesn't seem to work...
public function register()
{
$this->app->bind(BillerInterface::class, 'Vendor\Biller\Gateways\Paypal');
$this->app->bind(Biller::class, function ($app) {
return new Biller($app->make(BillerInterface::class));
});
}
Any clues?
Upvotes: 2
Views: 1397
Reputation: 5386
Talking about @MaGnetas
answer
I prefer to bind class with interface using this way.
public function register()
{
$this->app->bind(AppointmentInterface::class, AppointmentService::class);
}
This helps IDEs to find the path of the class and we can jump to that class by just clicking on it.
If we pass class path as string path like shown below:
public function register()
{
$this->app->bind('App\Interfaces\AppointmentInterface', 'App\Services\AppointmentService');
}
Then IDE can not find the location of class when we click on this string.
Upvotes: 0
Reputation: 39389
You’re binding interfaces to an implementation fine in your service provider. But dependencies will only be resolved by the service container, i.e.
class SomeClass
{
public function __construct(Billing $billing)
{
$this->billing = $billing;
}
}
Laravel’s service container will read the type-hint of the constructor method’s parameters, and resolve that instance (and also any of its dependencies).
You won’t be able to “new up” the Billing
instance directly (i.e. $billing = new Billing
) because the constructor is expecting something implementing BillingInterface
, which you’re not providing.
Upvotes: 2
Reputation: 7479
This is how I've done it in my app and it seems to be working:
public function register()
{
$this->app->bind('DesiredInterface', function ($app) {
return new DesiredImplementationClass(
$app['em'],
new ClassMetaData(DesiredClass::class)
);
});
}
Upvotes: 0
Reputation: 5108
When you're binding interface to actual class try replacing the BillerInterface::class
with a string '\Your\Namespace\BillerInterface'
Upvotes: 0