CodeIgniter4のコアクラスを拡張して使ってみた!(View編)
CodeIgniter4には便利なコアクラスがいくつか導入されています。
ライブラリリファレンス
コアクラスを使うことで、外部ライブラリを導入したときのバージョン問題や親和性がない等のリスクを減らせるのがコアクラスを使うメリットかと思います。 逆にコアクラスに実装されていないものに関しては、デフォルトでは実装できないという痒い所に手が届かないものになっています。
前回(CodeIgniter4のコアクラスを拡張して使ってみた!(Validation編))は、Validationクラスの拡張を行ってみました。
今回はライブラリではなくデフォルトで毎回オートロードされるコアシステムクラスの中でも使用頻度の高いViewクラスを拡張して使う方法をDocumentをもとにまとめていこうと思います。
筆者の環境
- PHP7.4.33
- CodeIgniter4.4.1
※ CodeIgniter4の環境は前前回の記事「CodeIgniter4にテンプレートエンジンのTwigを連携して、可読性・保守性を高いコードを実現する」で構築済のものを使います。
テスト用コントローラの作成
まずはテスト用に異なる二つのコントローラを作ります。
Controller
/app/Controllers/Viewtest.php
<?php
namespace App\Controllers;
class Viewtest extends BaseController
{
public function input(): string
{
return view('viewtest1');
}
}
/app/Controllers/Viewtest2.php
<?php
namespace App\Controllers;
class Viewtest2 extends BaseController
{
public function input(): string
{
return view('viewtest2');
}
}
View
/app/Views/viewtest.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="description" content="ディスクリプションが入ります">
<title>タイトルが入ります</title>
</head>
<body>
view1です。
</body>
</html>
/app/Views/viewtest2.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="description" content="ディスクリプションが入ります">
<title>タイトルが入ります</title>
</head>
<body>
view2です。
</body>
</html>
Config
/app/Config/Routes.php
$ git diff app/Config/Routes.php
diff --git a/app/Config/Routes.php b/app/Config/Routes.php
index d4260d4..fabcba0 100644
--- a/app/Config/Routes.php
+++ b/app/Config/Routes.php
@@ -3,6 +3,8 @@
use CodeIgniter\Router\RouteCollection;
use App\Controllers\Form;
+use App\Controllers\Viewtest;
+use App\Controllers\Viewtest2;
/**
* @var RouteCollection $routes
@@ -10,4 +12,7 @@ use App\Controllers\Form;
$routes->get('/', 'Home::index');
$routes->get('form', [Form::class, 'input']);
$routes->post('form', [Form::class, 'check']);
+
+$routes->get('viewtest', [Viewtest::class, 'input']);
+$routes->get('viewtest2', [Viewtest2::class, 'input']);
動作確認
http://localhost/xxxxx/viewtest
http://localhost/xxxxx/viewtest2
問題なく表示されていることが確認できました。
コアクラスの拡張
タイトルとディスクリプション部分を動的に変更し、データのアサインを拡張コアクラスで行います。
コアのViewクラスをエクステンドするクラスの作成
最初にタイトルとディスクリプションのプロパティを持ったクラスを作成します。
Viewクラスの機能を利用するためにコアクラスをエクステンドします。
View.php
/app/Core/View.php
<?php
namespace App\Core;
// コアクラスの呼び出し
use CodeIgniter\View\View as BaseView;
use Psr\Log\LoggerInterface;
class View extends BaseView
{
/**
* @var string
*/
public $title = '拡張クラスで設定しているタイトルです';
/**
* @var string
*/
public $description = '拡張クラスで設定しているディスクリプションです';
public function __construct($config, string $viewPath = null, $loader = null, bool $debug = null, LoggerInterface $logger = null)
{
parent::__construct($config, $viewPath, $loader, $debug, $logger);
}
}
※ Documentではapp/Librariesに設置していますが、コアクラスの拡張クラスと一目でわかるように、またCodeIgniter3のコア拡張クラスと同感覚で実装できるようにapp/Coreの中に設置しています。
Viewクラスの読み込みを上記で作成した拡張クラスに変更
Viewクラスの読み込みを変更する前にコアでViewクラスを読み込んでいる箇所を見てみます。
/vendor/codeigniter4/framework/system/config/Services.php
use CodeIgniter\View\Cell;
use CodeIgniter\View\Parser;
use CodeIgniter\View\RendererInterface;
use CodeIgniter\View\View; // ← ココでコアのViewクラスをuseして
class Services extends BaseService
{
~~ 中略 ~~
public static function renderer(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true)
{
if ($getShared) {
return static::getSharedInstance('renderer', $viewPath, $config);
}
$viewPath = $viewPath ?: (new Paths())->viewDirectory;
$config ??= config(ViewConfig::class);
// ココでインスタンス化している
return new View($config, $viewPath, AppServices::locator(), CI_DEBUG, AppServices::logger());
}
~~ 中略 ~~
}
コアクラスに手を入れたくないので、Services.phpもapp側でオーバーライドします。
Config
/app/Config/Services.php
$ git diff app/Config/Services.php
diff --git a/app/Config/Services.php b/app/Config/Services.php
index df7c8ad..fdacf04 100644
--- a/app/Config/Services.php
+++ b/app/Config/Services.php
@@ -3,6 +3,9 @@
namespace Config;
use CodeIgniter\Config\BaseService;
+use App\Core\View;
+use Config\Services as AppServices;
+use Config\View as ViewConfig;
/**
* Services Configuration file.
@@ -29,4 +32,16 @@ class Services extends BaseService
* return new \CodeIgniter\Example();
* }
*/
+
+ public static function renderer(?string $viewPath = null, ?ViewConfig $config = null, bool $getShared = true)
+ {
+ if ($getShared) {
+ return static::getSharedInstance('renderer', $viewPath, $config);
+ }
+
+ $viewPath = $viewPath ?: (new Paths())->viewDirectory;
+ $config ??= config(ViewConfig::class);
+
+ return new View($config, $viewPath, AppServices::locator(), CI_DEBUG, AppServices::logger());
+ }
}
CodeIgniter/View
ではなくapp/Core/View
を読み込み、実際にViewのインスタンスを返すrendererメソッドをオーバーライドしています。
Viewテンプレートでプロパティを読み込む
先ほど拡張Viewクラスで設定したプロパティをテンプレートで読み込みます。
View
$ git diff app/Views/
diff --git a/app/Views/viewtest1.php b/app/Views/viewtest1.php
index 094b740..567287b 100644
--- a/app/Views/viewtest1.php
+++ b/app/Views/viewtest1.php
@@ -2,8 +2,8 @@
<html lang="ja">
<head>
<meta charset="UTF-8">
- <meta name="description" content="ディスクリプションが入ります">
- <title>タイトルが入ります</title>
+ <meta name="description" content="<?= $this->description; ?>">
+ <title><?= $this->title; ?></title>
</head>
<body>
view1です。
diff --git a/app/Views/viewtest2.php b/app/Views/viewtest2.php
index 38acf50..c9a7062 100644
--- a/app/Views/viewtest2.php
+++ b/app/Views/viewtest2.php
@@ -2,8 +2,8 @@
<html lang="ja">
<head>
<meta charset="UTF-8">
- <meta name="description" content="ディスクリプションが入ります">
- <title>タイトルが入ります</title>
+ <meta name="description" content="<?= $this->description; ?>">
+ <title><?= $this->title; ?></title>
</head>
<body>
view2です。
動作確認
http://localhost/xxxxx/viewtest
http://localhost/xxxxx/viewtest2
どちらのテンプレートでも共通して拡張クラスのプロパティを表示できていることが確認できました!
まとめ
今回はCodeIgniter4のViewクラスを拡張して、共通の変数を設定してみました。 前回とは異なり、コアのServiceも拡張するという大がかりな拡張ではありましたが、CodeIgniterはデフォルトでこのような拡張性を持たせてくれているところも利点です。
用法容量を守ってこれからもCodeIgniter4で保守開発のしやすいコードづくりに取り組めたらなと思っています。
また、これからCodeIgniter4を用いて開発しようと考えている方の参考になれば幸いです。
この記事を書いた人
-
東京で2年半エンジニアとしての経験を積み、浜松にUターンの後、アーティスへ入社。
ソリューション事業部のWebエンジニアとして、システムの設計・開発・保守・運用からインフラまで幅広く従事している。
フルスタックエンジニア目指して現在も勉強の日々。車が好き。
この執筆者の最新記事
関連記事
最新記事
FOLLOW US
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー