CodeIgniter4のServicesとは?
この記事は CodeIgniter Advent Calendar 2022 - Qiita の12日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。
CodeIgniter4の基本的な機能であるServicesについての解説記事がなかったので、書くことにします。
Servicesとは?
CodeIgniter4のServicesとは、フレームワークが提供するサービスロケーターです。 CodeIgniter4が提供するクラスのほとんどは、このServicesから取得できます。
Servicesは要求されたサービスのオブジェクトを生成し返します。
また、ユーザーが自分で作成したクラスをServicesに追加することや、CodeIgniter4のコアクラスを置き換えることもできます。
サービスの取得方法
Servicesは Config\Services
クラスとして実装されています。各サービスを取得するメソッドが用意されているので、そのメソッドを呼び出せば、そのサービスのオブジェクトが取得できます。
$options = [
'baseURI' => 'http://example.com/api/v1/',
'timeout' => 3,
];
$client = \Config\Services::curlrequest($options);
上記のようにオプションで引数を渡せるサービスもあります。
共有オブジェクトの取得
ほとんどのサービスはデフォルトでは共有オブジェクトを返します。
最初にそのサービスのメソッドを呼んだときにインスタンスが生成され、その後、 何度同じメソッドを呼んでも、全く同じインスタンスが返るということです。
インスタンス化する際に渡される引数は、二度目以降の呼び出しでは無視されることに注意してください。
例えば、
$options1 = [
'baseURI' => 'http://example.com/api/v1/',
'timeout' => 5,
];
$client1 = \Config\Services::curlrequest($options1);
$options2 = [
'baseURI' => 'http://www.example.jp/api/v2/',
'timeout' => 3,
];
$client2 = \Config\Services::curlrequest($options2);
上のコードでは、$client1
と $client2
は全く同じインスタンスです。
二度目の呼び出し時には、すでにあるインスタンスを返すだけで新しいインスタンスは生成されないため、引数 $options2
は結果として無視されます。
新しいオブジェクトの取得
共有オブジェクトではなく、別の新しいインスタンスが必要な場合は、メソッドの引数 $getShared
に false
を渡します。
$options = [
'baseURI' => 'http://example.com/api/v1/',
'timeout' => 3,
];
$client = \Config\Services::curlrequest($options, null, null, false);
引数 $getShared
は全てのサービスで定義されており、
Services::encrypter()
以外のデフォルト値は true
です。
なお、実際のサービスは CodeIgniter\Config\Services
クラスに定義されています。
Servicesを使う範囲
Servicesは静的メソッドであり、どこからでも呼び出せます。
しかし、Servicesを使うと、呼び出し元のクラスがServicesに依存することになります。 この依存は本来不必要なものです。
ですから、Servicesはコントローラ内でのみ使うことが推奨されています。 それ以外のモデルやライブラリでは、Servicesを使うのではなく、必要なオブジェクトを外部から渡す(注入する)ようにしましょう。
サービスの追加方法
自分で作成したクラスをサービスとして追加できます。
Config\Services
にそのオブジェクトを生成して返すメソッドを追加するだけです。
<?php
namespace Config;
use App\Library\Twig;
use CodeIgniter\Config\BaseService;
class Services extends BaseService
{
// ...
public static function twig(bool $getShared = true): Twig
{
if ($getShared) {
return static::getSharedInstance('twig');
}
return new Twig();
}
}
これで、\Config\Services::twig()
を呼び出すと共有オブジェクトが返り、\Config\Services::twig(false)
を呼び出すと新しいオブジェクトが返ります。
コアクラスの置き換え
CodeIgniter4のコアクラスを置き換えたい場合は、 CodeIgniter\Config\Services
クラスで定義されているコアクラスのサービスのメソッドを Config\Services
にコピーして変更します。
<?php
namespace Config;
use App\Router\MyRouter;
use CodeIgniter\Config\BaseService;
use CodeIgniter\Router\RouteCollection;
class Services extends BaseService
{
// ...
public static function routes(bool $getShared = true): RouteCollection
{
if ($getShared) {
return static::getSharedInstance('routes');
}
return new MyRouter(static::locator(), config('Modules'));
}
}
service() 関数
関連する関数として、service()
と single_service()
が提供されています。
single_service()
は新しいインスタンスを返すものです。
これらの関数は Config\Services
のメソッドへのラッパーです。
しかし、Config\Services
のメソッドを直接呼び出せば、静的解析で返り値がわかるのに対し、
これらの関数を使うと返り値はわかりません。
ということでデメリットはあってもメリットがあまりなさそうなので、これらの関数の利用はお薦めしません。
まとめ
- Servicesは要求されたサービスのオブジェクトを返します。
- 自分の作成したクラスをServicesに追加することができます。
- CodeIgniter4のコアクラスを自分の作成したクラスに置き換えることもできます。
- Servicesはコントローラ内でのみ使いましょう。
この記事は CodeIgniter Advent Calendar 2022 - Qiita の12日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。
関連
参考
Date: 2022/12/12