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 は結果として無視されます。

新しいオブジェクトの取得

共有オブジェクトではなく、別の新しいインスタンスが必要な場合は、メソッドの引数 $getSharedfalse を渡します。

$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

Tags: codeigniter, codeigniter4