Laravel Service Container: Contextual Binding &amp; Injection | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com) [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles  ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

  [ home ](https://msaied.com)    [ articles ](https://msaied.com/articles)    Contextual Binding and Method Injection in Laravel's Service Container        On this page       1. [  Beyond app()-&gt;make(): The Container You're Not Using Fully ](#beyond-codeapp-gtmakecode-the-container-youre-not-using-fully)
2. [  Contextual Binding ](#contextual-binding)
3. [  Giving a Primitive Contextually ](#giving-a-primitive-contextually)
4. [  Tagged Services ](#tagged-services)
5. [  Method Injection ](#method-injection)
6. [  Method Injection in Artisan Commands ](#method-injection-in-artisan-commands)
7. [  Testing Contextual Bindings ](#testing-contextual-bindings)
8. [  Takeaways ](#takeaways)

  ![Contextual Binding and Method Injection in Laravel's Service Container](https://cdn.msaied.com/639/ce580b3b521a5e965bf80bb1e7ba7ced.png)

  #laravel   #service-container   #dependency-injection   #architecture  

 Contextual Binding and Method Injection in Laravel's Service Container 
========================================================================

     7 Sep 2026      3 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

1. [  01   Beyond app()-&gt;make(): The Container You're Not Using Fully  ](#beyond-codeapp-gtmakecode-the-container-youre-not-using-fully)
2. [  02   Contextual Binding  ](#contextual-binding)
3. [  03   Giving a Primitive Contextually  ](#giving-a-primitive-contextually)
4. [  04   Tagged Services  ](#tagged-services)
5. [  05   Method Injection  ](#method-injection)
6. [  06   Method Injection in Artisan Commands  ](#method-injection-in-artisan-commands)
7. [  07   Testing Contextual Bindings  ](#testing-contextual-bindings)
8. [  08   Takeaways  ](#takeaways)

 Beyond `app()->make()`: The Container You're Not Using Fully
------------------------------------------------------------

Most Laravel developers know `bind`, `singleton`, and `make`. That covers 80% of day-to-day container use. The remaining 20% — contextual binding, tagged services, and method injection — is where the container earns its keep in complex domain code. This article walks through each with production-grade examples.

---

Contextual Binding
------------------

Contextual binding answers the question: *what should the container inject when two different classes both depend on the same interface, but need different implementations?*

```php
// AppServiceProvider::register()
$this->app
    ->when(OrderProcessor::class)
    ->needs(PaymentGatewayInterface::class)
    ->give(StripeGateway::class);

$this->app
    ->when(SubscriptionRenewalJob::class)
    ->needs(PaymentGatewayInterface::class)
    ->give(BraintreeGateway::class);

```

Both `OrderProcessor` and `SubscriptionRenewalJob` type-hint `PaymentGatewayInterface`. The container resolves each to a different concrete without any conditional logic inside the classes themselves.

### Giving a Primitive Contextually

Contextual binding isn't limited to interfaces. You can inject config values or primitive scalars:

```php
$this->app
    ->when(S3Uploader::class)
    ->needs('$bucketName')
    ->give(fn () => config('filesystems.disks.s3.bucket'));

```

The `$bucketName` constructor parameter is resolved from config at build time — no `config()` call inside the class, no hidden coupling.

---

Tagged Services
---------------

Tagging lets you resolve a *collection* of implementations registered under a shared label. This is the clean alternative to a hand-rolled registry array.

```php
// Register
$this->app->bind(CsvExporter::class);
$this->app->bind(JsonExporter::class);
$this->app->bind(XlsxExporter::class);

$this->app->tag(
    [CsvExporter::class, JsonExporter::class, XlsxExporter::class],
    'exporters'
);

```

```php
// Resolve all tagged exporters
class ExportManager
{
    /** @param iterable $exporters */
    public function __construct(
        private readonly iterable $exporters
    ) {}
}

// In the service provider
$this->app->bind(ExportManager::class, fn ($app) =>
    new ExportManager($app->tagged('exporters'))
);

```

`$app->tagged()` returns a lazy generator — implementations are not instantiated until iterated. Adding a new exporter is a one-line tag registration; `ExportManager` never changes.

---

Method Injection
----------------

The container can inject dependencies into *arbitrary methods*, not just constructors. This is useful for controller actions, console commands, and domain handlers where you want to keep the constructor lean.

```php
class ReportController extends Controller
{
    public function generate(
        Request $request,
        ReportBuilder $builder,   // injected by container
        CacheManager $cache       // injected by container
    ): JsonResponse {
        // ...
    }
}

```

Laravel's router already does this for controller methods. You can invoke the same mechanism manually:

```php
$result = app()->call(
    [SomeService::class, 'handle'],
    ['extraParam' => $value]  // merge with container-resolved args
);

```

This is powerful inside pipeline stages, command handlers, or test helpers where you want full DI without making the class a singleton.

### Method Injection in Artisan Commands

```php
class SyncInventoryCommand extends Command
{
    public function handle(InventorySync $sync, LoggerInterface $log): int
    {
        $log->info('Starting sync');
        $sync->run();
        return self::SUCCESS;
    }
}

```

Artisan resolves `handle()` through the container automatically. No constructor injection needed for command-specific dependencies.

---

Testing Contextual Bindings
---------------------------

Swap a contextual binding in a test without touching the service provider:

```php
it('uses the sandbox gateway in tests', function () {
    $this->app
        ->when(OrderProcessor::class)
        ->needs(PaymentGatewayInterface::class)
        ->give(SandboxGateway::class);

    $processor = app(OrderProcessor::class);

    expect($processor->gateway())->toBeInstanceOf(SandboxGateway::class);
});

```

The override is scoped to the test; no global state leaks.

---

Takeaways
---------

- **Contextual binding** eliminates conditional logic inside classes when multiple implementations of an interface are needed in different contexts.
- **Primitive injection** (`needs('$param')`) keeps config and environment values out of class bodies.
- **Tagged services** replace hand-rolled registries with a lazy, extensible collection resolved by the container.
- **Method injection via `app()->call()`** gives you full DI on any callable — useful in pipelines, handlers, and tests.
- All of these are testable in isolation: swap bindings per-test without touching service providers.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Fcontextual-binding-and-method-injection-in-laravels-service-container-3&text=Contextual+Binding+and+Method+Injection+in+Laravel%27s+Service+Container) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Fcontextual-binding-and-method-injection-in-laravels-service-container-3) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  When should I use contextual binding instead of a factory or strategy pattern?        Use contextual binding when the decision of which implementation to use is purely about *which class is being constructed*, not runtime data. If the choice depends on user input or a database value, a factory or strategy resolved at runtime is more appropriate. 

      Q02  Does `app()-&gt;tagged()` instantiate all services immediately?        No. `app()-&gt;tagged()` returns a generator. Each implementation is resolved lazily as you iterate, so unused implementations in the collection are never instantiated. 

      Q03  Can I use method injection outside of controllers and Artisan commands?        Yes. `app()-&gt;call($callable, $parameters)` works on any callable — closures, static methods, or instance methods. The container merges your explicit parameters with anything it can resolve by type-hint. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://msaied.com/articles) 

 [ ![Filament v4 Schema-Based Forms: Unified Schema API and Infolist Patterns](https://cdn.msaied.com/638/f9bf7d5a5195f8a61e97ccc196cf96d6.png) filament laravel filament-v4 

### Filament v4 Schema-Based Forms: Unified Schema API and Infolist Patterns

Filament v4 replaces scattered form/infolist definitions with a single Schema API. Learn how unified schemas,...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 7 Sep 2026     3 min read  

  Read    

 ](https://msaied.com/articles/filament-v4-schema-based-forms-unified-schema-api-and-infolist-patterns) [ ![The Pipeline Pattern in Laravel: Building Custom Pipelines Beyond Middleware](https://cdn.msaied.com/637/1b6b067bc3805768f8e1f546d2ba7545.png) laravel pipeline clean-architecture 

### The Pipeline Pattern in Laravel: Building Custom Pipelines Beyond Middleware

Laravel's Pipeline class powers middleware, but it's equally powerful for domain workflows. Learn how to build...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 6 Sep 2026     3 min read  

  Read    

 ](https://msaied.com/articles/the-pipeline-pattern-in-laravel-building-custom-pipelines-beyond-middleware-2) [ ![Eloquent N+1 Elimination: Eager Loading Strategies and Query Deduplication at Scale](https://cdn.msaied.com/636/87a71d1826f8c6cce958da8377a0bdb9.png) laravel eloquent performance 

### Eloquent N+1 Elimination: Eager Loading Strategies and Query Deduplication at Scale

N+1 queries silently destroy Laravel app performance. This guide covers eager loading strategies, query dedupl...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 6 Sep 2026     4 min read  

  Read    

 ](https://msaied.com/articles/eloquent-n1-elimination-eager-loading-strategies-and-query-deduplication-at-scale) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [Contact](https://msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
