これは、一般的に Symfony2 に含まれるサードパーティのバンドルに対する回答でありcomposer
、特別なバンドルについて言及するものではありません。
初めに
要求されたバンドルのバージョンを安定したバージョン ( など1.*
) に修正composer.json
している限り (および開発者が独自のガイドラインに従っている限り)、インターフェースの互換性の問題に問題はないはずです。ラッピングは不要です。
しかし、ラッパー コードで例外をスローしたり、フォールバックを実装したりして、コードの中断を防ぎたいと考えています。これにより、ラッパー コードを使用するすべてのものが引き続き機能するか、少なくとも適切なエラーが表示されます。
ラッピングしたい場合
dev-master
特定のサードパーティ バンドルのバージョンを使用する場合、大幅な変更が発生する可能性があります。しかし、安定したバージョンがあるときに本当にを含めたい場合はありません。dev-master
dev-master
とにかく、エラーを表示したり、ログに記録したり、例外をキャッチしたりするためにエラーを含めたい場合、またはラップしたい場合に意味があると思われる2つの方法があります。
サードパーティ バンドルのサービスのすべてのインスタンスを使用する単一のサービス クラスを構築する
このサービス クラスは、サード パーティのバンドルを使用するバンドルの 1 つに含まれている可能性があります。このアプローチでは、追加のバンドルは必要ありません。
acme.thirdparty.client
このようにして、他のサービスの単一のメソッド呼び出しをラップするような単一のサービスを作成できます。必要なすべてのサードパーティ サービスを注入し (または必要なサブクラスのインスタンスを作成し)、必要なすべてのメソッド呼び出しをラップする必要があります。
# src/Acme/MyBundle/Resources/config/services.yml
parameters:
acme.thirdparty.wrapper.class: Acme\MyBundle\Service\WrapperClass
services:
acme.thirdparty.wrapper:
class: %acme.thirdparty.wrapper.class%
arguments:
someService: @somevendor.somebundle.someservice
someOtherService: @somevendor.somebundle.someotherservice
そしてサービスクラス:
<?php
namespace Acme\MyBundle\Service;
use SomeVendor\SomeBundle\SomeService\ConcreteService;
use SomeVendor\SomeBundle\SomeService\OtherConcreteService;
class WrapperClass
{
private $someService;
private $someOtherService;
public function __construct(ConcreteService $someService, OtherConcreteService $someOtherService)
{
$this->someService = $someService;
$this->someOtherService = $someOtherService;
}
/**
* @see SomeVendor\SomeBundle\SomeService\ConcreteService::someMethod
*/
public function someMethod($foo, $bar = null)
{
// Do stuff
return $this->someService->someMethod();
}
/**
* @see SomeVendor\SomeBundle\SomeService\ConcreteOtherService::someOtherMethod
*/
public function someOtherMethod($baz)
{
// Do stuff
return $this->someOtherService->someOtherMethod();
}
}
次に、これらのメソッド呼び出しにエラー処理を追加して (すべての例外をキャッチしてログに記録するなど)、サービス クラスの外部のコードが破損するのを防ぐことができます。ただし、言うまでもなく、これによってサードパーティ バンドルの予期しない動作が防止されるわけではありません。
または、次のことができます。
複数のサービスを含むバンドルを作成し、それぞれがサード パーティ バンドルの 1 つのサービスをラップします。
バンドル全体には、正確にラップしたいものに対してより柔軟であるという利点があります。サービス全体または単一のリポジトリのみをラップし、ラップされたクラスを独自のものに置き換えることができます。DI コンテナーを使用すると、次のように、注入されたクラスをオーバーライドできます。
# src/Acme/WrapperBundle/Resources/config/services.yml
parameters:
somevendor.somebundle.someservice.class: Acme\WrapperBundle\Service\WrapperClass
クラス パラメータをオーバーライドすることにより、somevendor.somebundle.someservice.class
このクラスを使用するすべてのサービスが のインスタンスになりますAcme\WrapperBundle\Service\WrapperClass
。このラッパー クラスは、基本クラスを拡張することができます。
<?php
namespace Acme\WrapperBundle\Service;
use SomeVendor\SomeBundle\SomeService\ConcreteService;
class WrapperClass extends ConcreteService
{
/**
* @see ConcreteService::someMethod
*/
public function someMethod($foo, $bar = null)
{
// Do stuff here
parent::someMethod($foo, $bar);
// And some more stuff here
}
}
...または元のクラスのインスタンスを使用してラップすることもできます:
<?php
namespace Acme\WrapperBundle\Service;
use SomeVendor\SomeBundle\SomeService\ConcreteServiceInterface;
use SomeVendor\SomeBundle\SomeService\ConcreteService;
class WrapperClass implements ConcreteServiceInterface
{
private $someService;
/**
* Note that this class should have the same constructor as the service.
* This could be achieved by implementing an interface
*/
public function __construct($foo, $bar)
{
$this->someService = new ConcreteService($foo, $bar);
}
/**
* @see ConcreteService::someMethod
*/
public function someMethod($foo, $bar = null)
{
// Do stuff here
$this->someService->someMethod($foo, $bar);
// And some more stuff here
}
}
別のクラスをオーバーライドしているクラスのインターフェイスを実装することが必須になる場合があることに注意してください。また、2 番目のものは最良のアイデアではない可能性がありますConcreteService
。これは、単に置き換えるだけでなく、実際に をラップしているのかどうかがはっきりしないためです。また、これは依存性注入の考え方全体を無視しています。
このアプローチは、より多くの作業を必要とし、より多くのテストを意味しますが、より柔軟性が必要な場合は、これが適しています。
おそらく、目的のサード パーティ バンドルのラッパー バンドルが既に存在する可能性があります ( のSensioBuzzBundle
場合Buzz Browser
など)。
結論
開発者を信頼し、安定したバージョン (1.*
バグ修正と新機能、または1.0.*
バグ修正のみなど) を含めることが道です。安定したバージョンがない場合、または を含めたい場合はdev-master
、ラッピングがオプションです。コードをラップする場合は、追加のバンドルを構築する方がより柔軟な方法ですが、ラップするコードがあまりない場合は、単一のサービス クラスで十分な場合があります。