1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravelのサービスコンテナのextendは抽象と実装両方とも反応する

Last updated at Posted at 2020-12-24

ReadDoubleのサービスコンテナの章に、結合の拡張と書いてあるのが目に入り、実装を拡張するのかインターフェースをデコレートできるのかどっちだろうと気になったので調べてみたら両方反応しました。色々使えそう。

コード

Foo.php
interface Foo
{
    /**
     * 関数の説明
     */
    public function getString(): string;
}
FooImpl.php
/**
 * クラスの説明
 */
class FooImpl implements Foo
{
    private $bar = 'default';

    /**
     * 関数の説明
     */
    public function setString(string $new): void
    {
        $this->bar = $new;
    }

    /** {@inheritdoc} */
    public function getString(): string
    {
        return $this->bar;
    }
}
FooDecorator.php
/**
 * クラスの説明
 */
class FooDecorator implements Foo
{
    public function __construct(Foo $base)
    {
        $this->base = $base;
    }

    /** @var Foo */
    private $base;

    /** {@inheritdoc} */
    public function getString(): string
    {
        return 'decorated ' . $this->base->getString();
    }
}
AppServiceProvider.php
class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->extend(Foo::class, function (Foo $service, $app) {
            return new FooDecorator($service);
        });
        $this->app->extend(FooImpl::class, function (FooImpl $service, $app) {
            $service->setString('and changed');
            return $service;
        });
    }

    public $bindings = [
        Foo::class => FooImpl::class
    ];
}
FooController.php
class FooController extends Controller
{
    public function __invoke(Foo $foo): array
    {
        return ['message' => $foo->getString()];
    }
}
FooControllerTest.php
class FooControllerTest extends \Tests\TestCase
{
    use MockeryPHPUnitIntegration;

    /**
     * @test
     */
    public function fooTest(): void
    {
        $this->withoutExceptionHandling();

        $response = $this->get('/foo');

        $response->assertJson(['message' => 'decorated and changed']);
    }
}

 実行結果

$ php artisan test --filter FooControllerTest

   PASS  Tests\Feature\App\Http\Controllers\FooControllerTest
  ✓ foo test

  Tests:  1 passed
  Time:   6.73s
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?