アナログCPU:5108843109

ゲームと音楽とプログラミング(酒と女とロックンロールのノリで)

('ω') < イザユケエンジニャー

CodeIgniter入門 #4:自作コアクラスを挟んでみる

CodeIgniter入門シリーズ カテゴリーの記事一覧 - アナログCPU:5108843109


CodeIgniterにデフォルトで入っているWelcomeコントローラは以下のように始まっています。

class Welcome extends CI_Controller { ...

これはsystem(コアシステム)内のクラスを継承しているのですが、
いろんなところで共通の処理を独自に入れたい、というときにsystem内をいじるのはあまりよろしくありません。
CI_Controllerを継承した独自のクラスをさらに継承して使いたいと思います。

今回やること

  • コアクラスとコントローラの間に自作のクラスを挟む

まずはドキュメントを見る

コアシステムクラスの作成 — CodeIgniter 3.2.0-dev ドキュメント

要約すると…

  • application/core の下に自作クラスを設置する
  • クラス名は「MY_」で始めること
    • application/config/config.php 内で変更は可能、ただし「CI_」は不可
  • コントローラの継承元を自作クラスにする

…という感じですね。

やってみる

application/core/TestClass.php

<?php
class MY_Controller extends CI_Controller {
}

application/controller/Welcome.php

<?php
class Welcome extends MY_Controller {
	public function index()
	{
		echo "test";
	}
}

まずはシンプルに用意してみたのですが…

…動かない…。

Fatal error: Class 'MY_Controller' not found in ... Welcome.php on line 3

と言われてしまいます。

作ったクラスが読み込まれていないっぽい?

エラーメッセージでググってみる。

CodeIgniter Coreファイルが見つからない | ZEKIOM.NET
php - codeigniter MY_Controller not found - Stack Overflow
php - CodeIgniter 3.1.7 - Class 'MY_Controller' not found error occurred only on my server - Stack Overflow

解決していたりしていなかったりですが、このへんを参考にしつつ、
試しにWelcome.phpの先頭に

include_once(APPPATH.'core/TestClass.php');

を入れてみたら動きました。
どうやら読み込まれていなかった様子。デフォルトでは読まれないのか?
じゃあどこで読み込むべきなんだろうかとソースコードgrepしていると、
system/core/CodeIgniter.php 内にこんなものを見つけました。

if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'))
{
	require_once APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';
}

これはまさかとクラスのファイル名をMY_Controller.phpにしてみたら、動いた。

えええ…。
でも公式ドキュメントの例だと some_class.php とかいう適当な名前なんですけど…。
coreディレクトリ以下をまるっと読んだりしてくれないの?

複数ファイルを使い分けたりできないのかと考えるとしっくりこないのでもう少し探してみたのですが、
system/core/Common.php 内の load_class とかいう関数が怪しいかなーと思いつつ、これもまたしっくりこないので諦めた。
とりあえずMY_Controller.php で乗り切ることにします。

MY_Controller.php をなんとか使いまわす方法

この方法が正しいのかどうかはわかりませんが…
Step 9 - No more MY_Controller monopoly. How you can create more than one base controller - Avenir
を参考に。

複数のクラスを使いたくなったら、こんな感じで乗り切るのがお手軽かも。
ロードする順番に気を使わなくて済むし。

<?php
class MY_Controller extends CI_Controller
{
    // ...
}
 
class A_Controller extends MY_Controller
{
    // ...
}
 
class B_Controller extends MY_Controller
{
    // ...
}