PHP interfaces how to use them and Laravel interface binding simply explained
Published: 2024-05-27 13:03:08

##What is a PHP Interface?

An interface in PHP is a blueprint for classes. It defines a contract that any implementing class must adhere to, specifying methods that must be implemented but not providing the method bodies. Interfaces ensure a consistent structure across different classes and enable polymorphism by allowing multiple classes to be treated through a common interface. You can read more about it [here](https://dev.to/vimuth7/php-interfaces-and-their-usage-with-dependency-injection-18cl)

##Use without binding
Let's first talk about how to use interfaces without binding in laravel. 

**1.Define an Interface:**

Create an interface in the App\Contracts directory.

```
// app/Contracts/PaymentGatewayInterface.php
namespace App\Contracts;

interface PaymentGatewayInterface {
    public function charge($amount);
}
```

**2.Implement the Interface with Additional Methods:**

```
// app/Services/StripePaymentGateway.php
namespace App\Services;

use App\Contracts\PaymentGatewayInterface;

class StripePaymentGateway implements PaymentGatewayInterface {
    public function charge($amount) {
        // Logic to charge using Stripe
        return "Charged {$amount} using Stripe";
    }
}
```

**3.Inject the Implementation Manually:**
When you instantiate the controller or the class that requires the interface, manually provide the implementation.

```
// app/Http/Controllers/PaymentController.php
namespace App\Http\Controllers;

use App\Contracts\PaymentGatewayInterface;
use App\Services\StripePaymentGateway;

class PaymentController extends Controller {
    protected $paymentGateway;

    public function __construct(PaymentGatewayInterface $paymentGateway) {
        $this->paymentGateway = $paymentGateway;
    }

    public function charge($amount) {
        return $this->paymentGateway->charge($amount);
    }
}

```

```
// routes/web.php
use App\Http\Controllers\PaymentController;
use App\Services\StripePaymentGateway;

Route::get('/charge/{amount}', function ($amount) {
    $paymentGateway = new StripePaymentGateway();
    $controller = new PaymentController($paymentGateway);
    return $controller->charge($amount);
});
```

##Example with binding and benefits of the approach

Laravel's service container can automatically resolve dependencies for you, reducing boilerplate code. Check this example.

```
// app/Providers/AppServiceProvider.php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Contracts\PaymentGatewayInterface;
use App\Services\StripePaymentGateway;

class AppServiceProvider extends ServiceProvider {
    public function register() {
        $this->app->bind(PaymentGatewayInterface::class, StripePaymentGateway::class);
    }

    public function boot() {
        //
    }
}
```

```
// app/Http/Controllers/PaymentController.php
namespace App\Http\Controllers;

use App\Contracts\PaymentGatewayInterface;
use App\Services\StripePaymentGateway;

class PaymentController extends Controller {
    protected $paymentGateway;

    public function __construct(PaymentGatewayInterface $paymentGateway) {
        $this->paymentGateway = $paymentGateway;
    }

    public function charge($amount) {
        return $this->paymentGateway->charge($amount);
    }
}
```

With this binding in place, you don't need to manually instantiate StripePaymentGateway. So this code is enough inside routes.

```
// routes/web.php
use App\Http\Controllers\PaymentController;

Route::get('/charge/{amount}', [PaymentController::class, 'charge']);
```

In this example we have used **service binding** in Laravel. Service binding is used to register a concrete implementation for a given interface or abstract class in Laravel's service container. This allows Laravel to automatically resolve dependencies and inject the appropriate implementations when needed.