CodeIgniter 4.3 最速マスター
CodeIgniter 4に関する情報は 「CodeIgniter 4 まとめ」 を参照してください。
(最終更新:2023/01/27)
インストール&設定
インストール
Composerでインストールすると簡単です。
$ composer create-project codeigniter4/appstarter {フォルダ名}
フォルダ構成
CodeIgniter 4.3 のフォルダ構成は以下のようになっています。
ci4app/
├── app/ ... アプリケーション
│ ├── Common.php
│ ├── Cells/ ... (ビューセル)
│ ├── Commands/ ... (コマンド)
│ ├── Config/ ... 設定
│ ├── Controllers/ ... コントローラ
│ ├── Database/ ... データベース
│ ├── Entities/ ... (エンティティ)
│ ├── Filters/ ... コントローラフィルタ
│ ├── Helpers/ ... ヘルパー
│ ├── Language/ ... 言語ファイル
│ ├── Libraries/ ... ライブラリ
│ ├── Models/ ... モデル
│ ├── ThirdParty/ ... サードパーティライブラリ用
│ ├── Validation/ ... (バリデーションルール)
│ └── Views/ ... ビュー
├── builds* ... buildsコマンド
├── composer.json
├── composer.lock
├── env ... 環境変数設定ファイルのサンプル
├── phpunit.xml.dist
├── public/ ... Web公開領域(ドキュメントルート)
│ ├── favicon.ico
│ ├── index.php
│ └── robots.txt
├── spark* ... sparkコマンド
├── tests/ ... テストファイル
│ ├── _support/
│ ├── database/
│ ├── session/
│ └── unit/
├── vendor/ ... Composer管理
└── writable/ ... 書き込み用フォルダ
├── cache/ ... キャッシュファイル
├── debugbar/ ... デバッグバー用
├── logs/ ... ログファイル
├── session/ ... セッションファイル
└── uploads/ ... アップロードファイル
システムメッセージの翻訳のインストール
Composerで最新の開発版の翻訳をインストールします。
$ composer require codeigniter4/translations:dev-develop
設定
📕設定
設定ファイル
app/Config/
フォルダに設定ファイルがあります。設定ファイルはクラスです。
本番環境と共通の設定項目は、設定ファイルを変更します。
特に設定を変更しなくてもCodeIgniterは動作しますが、app/Config/App.php
の以下の項目は多くの場合、変更することになるでしょう。
$indexPage
... URLにindex.phpを付けない場合は、この設定を空文字にする$defaultLocale
... デフォルトのロケール('ja'
に変更すると日本語のシステムメッセージが使用されます)$supportedLocales
... サポートするロケール(優先順位が高い順に記載する)$appTimezone
... タイムゾーン
開発環境固有の設定項目(データベースのパスワードなど)は、env
ファイルを .env
にコピーして、そこに設定します。
設定クラスのプロパティに対応する環境変数があると、設定ファイルのインスタンス化時に環境変数の値が自動的に設定されます。
複数の環境
デフォルトでは、CodeIgniterは本番環境(production
)用に動作します。
エラーが発生してもページには表示されません。
開発環境では development
を指定します。これで開発モードになり、詳細なエラーやデバッグツールバーが表示されます。
.env
で設定できます。
CI_ENVIRONMENT = development
なお、testing
はPHPUnitでのテストのための特別な環境です。通常の開発やステージング環境には使えません。
データベース設定
app/Config/Database.php
に設定クラスがあります。
設定クラスの値を変更したい開発環境固有の設定項目は、以下のように .env
に設定します。
.env
database.default.hostname = localhost
database.default.database = ci4app
database.default.username = dbuser
database.default.password = dbpassword
サーバの起動
spark
コマンドでPHPビルトインサーバーが起動します。
$ php spark serve
http://localhost:8080/ にアクセスしてください。
ルーティング
CodeIgniter v4.2.0から、セキュリティ上の理由で自動ルーティングはデフォルトでオフになりました。
セキュリティ上の理由から、自動ルーティング(レガシー)は推奨しません。 できる限り、自動ルーティング(レガシー)は使用せず、「手動ルーティングのみ」または「自動ルーティング(改善)」を使いましょう。
手動ルーティング
HTTPメソッドでのルーティング
app/Config/Routes.php
にルートを設定します。
GETメソッドの場合は、$routes->get()
を使用します。
use App\Controllers\News;
$routes->get('news', [News::class, 'index']);
上記は、http://localhost:8080/news
にブラウザからアクセスすると、News
コントローラの index()
メソッドが呼び出されます。
POSTメソッドの場合は、$routes->post()
を使用します。
$routes->post('news/create', [News::class, 'create']);
上記は、http://localhost:8080/news/create
にPOSTすると、News
コントローラの create()
メソッドが呼び出されます。
URLの一部をキャプチャ
(:segment)
、(:any)
などのプレースホルダーを使います。
(:segment)
は1つのURIセグメント、(:any)
は任意の文字列にマッチします。
$routes->get('news/(:segment)', [News::class, 'view']);
上記は、/news/foo
の場合に、News
コントローラの view()
メソッドに foo
を渡します。
なお、上記は、以下のように書くこともできます。
$routes->get('news/(:segment)', '\App\Controllers\News::view/$1');
グループ化
ルートをグループ化することもできます。
$routes->group('admin', function ($routes) {
$routes->get('users', [\App\Controllers\Admin\Users::class, 'index']);
$routes->get('blog', [\App\Controllers\Admin\Blog::class, 'index']);
});
上記は、admin/users
と admin/blog
のルートを設定しています。
ルートの確認
spark routes
コマンドでルートを確認できます。上に表示されたルートが優先されます。
$ php spark routes
自動ルーティング(改善)
CodeIgniter v4.1.x までデフォルトだった自動ルーティングは、あまりにも簡単に脆弱性を作り込んでしまうため、 v4.2.0 からは、より安全な「自動ルーティング(改善)」が追加されました。
自動ルーティング(改善)を有効にする
自動ルーティング(改善)を有効にするには、app/Config/Routes.php
と app/Config/Feature.php
の 2箇所で設定する必要があります。
app/Config/Routes.php
$routes->setAutoRoute(true);
app/Config/Feature.php
public bool $autoRoutesImproved = true;
$autoRoutesImproved
が false
だと、自動ルーティング(レガシー)になります。
自動ルーティング(改善)の基本
基本的に以下の規約で自動的にルーティングします。
http://localhost:8080/{コントローラ名}/{メソッド名(HTTP動詞を除く)}/{引数1}/{引数2}/...
以下の News
コントローラを作成します。
<?php
namespace App\Controllers;
class News extends BaseController
{
public function getTest($p1 = 'x', $p2 = 'x')
{
return '$p1: ' . esc($p1) . ', $p2: ' . esc($p2);
}
}
すると、以下のルートが自動的に定義されます。
+-----------+---------------------+------------------------------------------+----------------+---------------+
| Method | Route | Handler | Before Filters | After Filters |
+-----------+---------------------+------------------------------------------+----------------+---------------+
| GET(auto) | news/test[/..][/..] | \App\Controllers\News::getTest | | toolbar |
+-----------+---------------------+------------------------------------------+----------------+---------------+
getTest()
メソッドの最初の get
はHTTPメソッド(HTTP動詞)です。この場合はGETメソッドでこのルートにアクセスできることになります。
例えば、POSTメソッドでアクセスさせたい場合は、postTest()
メソッドを定義する必要があります。
php spark serve
コマンドを実行し、
http://localhost:8080/news/test/a/b
にブラウザからアクセスすると、以下が表示されます。
$p1: a, $p2: b
http://localhost:8080/news/test/a
にアクセスすると、以下が表示されます。
$p1: a, $p2: x
http://localhost:8080/news/test
にアクセスすると、以下が表示されます。
$p1: x, $p2: x
http://localhost:8080/news/test/a/b/c
にアクセスすると、404 - File Not Found
が表示されます。
引数の数が合わないからです。
デフォルトメソッド
http://localhost:8080/news
でアクセス可能にするには、以下のように getIndex()
メソッドを追加します。
<?php
namespace App\Controllers;
class News extends BaseController
{
// ...
public function getIndex()
{
return __METHOD__;
}
}
これで http://localhost:8080/news
にアクセスすると、以下が表示されます。
App\Controllers\News::getIndex
このようにURLの {メソッド名(HTTP動詞を除く)}
の部分を省略したときに実行されるメソッドを「デフォルトメソッド」と言います。
デフォルトでは index
が設定されています。
デフォルトコントローラ
http://localhost:8080/
のように {コントローラ名}
がないURLにアクセス可能にするには、以下のように Home
コントローラを作成します。
<?php
namespace App\Controllers;
class Home extends BaseController
{
public function getIndex()
{
return view('welcome_message');
}
}
しかし、デフォルトでは app/Config/Routes.php
に /
へのルート(以下)が定義されています。
$routes->get('/', 'Home::index');
定義済みのルートは自動ルーティングより優先されるので、Home::index()
メソッドが存在しないため、404 - File Not Found
になります。
そこで、上記のルートの定義をコメントアウトしてください。
//$routes->get('/', 'Home::index');
これで、http://localhost:8080/
に自動ルーティング(改善)によりアクセス可能になります。
自動ルーティング(改善)の規約
- URLは基本的にはすべて小文字を想定
- URLでの
{コントローラ名}
はすべて小文字、実際のクラス名は先頭のみ大文字- サブフォルダを使う場合は、サブフォルダ名も先頭のみ大文字
- メソッド名には
getIndex()
、postCreate()
のようにHTTP動詞のプリフィックスが必要http://localhost:8080/news/create
にGETメソッドでリクエストした場合、News
コントローラのgetCreate()
メソッドが実行される
- メソッド名が省略されたURLの場合、デフォルトメソッド(デフォルトでは
index
)があれば実行されるhttp://localhost:8080/news
にGETメソッドでリクエストした場合、News
コントローラのgetIndex()
メソッドが実行される
- トップページへのリクエストの場合、デフォルトコントローラ(デフォルトでは
Home
)が実行されるhttp://localhost:8080/
にGETメソッドでリクエストした場合、Home
コントローラのgetIndex()
メソッドが実行される
- デフォルトコントローラとデフォルトメソッドはURLの中で必ず省略する必要がある
http://localhost:8080/
にはアクセス可能だがhttp://localhost:8080/home
には 404 が返るhttp://localhost:8080/news
にはアクセス可能だがhttp://localhost:8080/news/index
には 404 が返る
- メソッドのパラメータ数がチェックされる
- パラメータ数が一致しない場合は 404 が返る
- 手動ルーティングで定義されているコントローラには一切アクセスできない
- 手動ルーティングするコントローラと自動ルーティングするコントローラは厳密に区別される
News::index()
へのルートが手動ルーティングで設定されている場合、News::getCreate()
メソッドを追加してnews/create
にアクセスしても 404 が返る
_remap()
メソッドはサポートされない
コントローラ
コントローラの作成
sparkコマンドで作成できます。
$ php spark make:controller {コントローラクラス名}
以下のようなファイルが作成されます。
app/Controllers/Blog.php
<?php
namespace App\Controllers;
use App\Controllers\BaseController;
class Blog extends BaseController
{
public function index()
{
//
}
}
コントローラは、BaseController
を継承します。
$this->request
(Requestオブジェクト) と $this->response
(Responseオブジェクト)が使えます。
リクエストパラメータの取得
$this->request->getPost()
、$this->request->getGet()
、$this->request->getJsonVar()
を使います。
$this->request->getPost('title')
上記は、POSTされた title
の値を取得します。
バリデーション
$this->validateData()
を使います。
$data = [
'title' => $this->request->getPost('title'),
'body' => $this->request->getPost('body'),
];
$rules = [
'title' => ['label' => 'タイトル', 'rules' => ['required', 'max_length[100]']],
'body' => ['label' => '本文', 'rules' => 'required'],
];
if ($this->request->is('post') && $this->validateData($data, $rules)) {
// 検証パス
} else {
// 検証エラー
}
CodeIgniter v4.3.0から、$this->request->is()
メソッドでHTTPメソッドを判定できます。
エラーメッセージの上書き
$this->validateData()
の第3引数にエラーメッセージを指定します。
if ($this->request->is('post') && $this->validateData(
$data,
$rules,
[
'title' => [
'required' => 'タイトルは必須です。',
],
]
)) {
// 検証パス
}
独自の検証ルールの作成
app/Config/Validation.php
の $ruleSets
に検証ルールを実装したクラス名を追加します。
public $ruleSets = [
Rules::class,
FormatRules::class,
FileRules::class,
CreditCardRules::class,
\App\Libraries\Validation\MyRules::class,
];
検証ルールを実装したクラスは以下のようになり、バリデーションルール even
が使えるようになります。
namespace App\Libraries\Validation;
class MyRules
{
public function even($str, string &$error = null): bool
{
if ((int) $str % 2 !== 0) {
$error = 'エラーメッセージ。';
return false;
}
return true;
}
}
クロージャルールの作成
CodeIgniter v4.3.0から、一箇所でしか使わないルールはクロージャで定義することもできます。
$rules = [
'foo' => [
'required',
static function ($value, $data, &$error, $field) {
if ((int) $value % 2 === 0) {
return true;
}
$error = 'エラーメッセージ。';
return false;
},
],
];
if ($this->request->is('post') && $this->validateData($data, $rules)) {
// 検証パス
}
モデルの呼び出し
📕model() 関数を使います。
$model = model(UserModel::class);
ビューのレンダリング
📕view() 関数を使います。
return view('pages/view_filename', $data);
第1引数はビューファイル名、第2引数はビューに渡すデータの配列です。
ビューファイル名、app/Views/
以下のファイルパスを .php
を除いて指定します。
ログの出力
📕log_message() 関数を使います。
log_message('debug', 'デバッグ用のログメッセージ。');
ログファイルは、writable/logs/
に日付別に作成されます。
リダイレクト
📕redirect() 関数を使います。
return redirect()->to('home/index');
リダイレクトさせるには、RedirectResponse
オブジェクトを返す必要があります。
API
ルーティング
app/Config/Routes.php
$routes->resource('photos');
上記を設定すると、以下のルートが設定されたことになります。
$routes->get('photos/new', 'Photos::new');
$routes->post('photos', 'Photos::create');
$routes->get('photos', 'Photos::index');
$routes->get('photos/(:segment)', 'Photos::show/$1');
$routes->get('photos/(:segment)/edit', 'Photos::edit/$1');
$routes->put('photos/(:segment)', 'Photos::update/$1');
$routes->patch('photos/(:segment)', 'Photos::update/$1');
$routes->delete('photos/(:segment)', 'Photos::delete/$1');
不要なメソッドがあれば、除外指定します。
$routes->resource('photos', ['except' => 'new,edit']);
コントローラ
ResourceController
を継承します。
<?php
namespace App\Controllers;
use App\Models\PhotoModel;
use CodeIgniter\RESTful\ResourceController;
class Photos extends ResourceController
{
protected $modelName = PhotoModel::class;
protected $format = 'json';
public function index()
{
return $this->respond($this->model->findAll());
}
// ...
}
ResponseTrait
に実装されている $this->respond()
などのメソッドが使えるようになります。
上記のコードでは、モデルを検索した結果がJSONで返されます。
ビュー
📕ビュー
デフォルトでは、ビューファイルは普通のPHPファイルです。
個人的には、出力時に自動でエスケープ処理してくれるTwigなどのテンプレートエンジンかView Parserの使用を推奨します。
デフォルトのView
コントローラから渡された配列が、 キーを変数名とした変数に設定されます。
変数を出力する場合は、忘れずに esc()
関数でエスケープします。
View Parser
テンプレートエンジンです。変数の値の自動HTMLエスケープやフィルター機能も提供します。
コントローラから渡された配列の値が {blog_title}
のような疑似変数に表示されます。
値は自動的にHTMLエスケープされます。
{ }
はJavaScriptと相性が悪いので、設定で {{ }}
に変更することをお薦めします。
モデル
CodeIgniter\Model
が標準で提供されていますが、使わなくても構いません。
データベース操作が必要な場合、 最小限のモデルクラスは以下のようになります。
app/Models/UserModel.php
<?php
namespace App\Models;
use CodeIgniter\Database\ConnectionInterface;
class UserModel
{
protected $db;
public function __construct(ConnectionInterface $db)
{
$this->db = $db;
}
}
$db
はインスタンス化する時に自分で注入してください。
モデルの作成
以下のようなファイルを作成します。
app/Models/UserModel.php
<?php
namespace App\Models;
use CodeIgniter\Model;
class UserModel extends Model
{
protected $table = 'users';
}
CodeIgniter\Model
を継承すると、いろいろ便利な機能が使えます。
クエリビルダー
ビルダーの生成
db_connect()
関数で「データベース接続」オブジェクトを取得できます。
$db = db_connect();
データベース接続オブジェクトの table()
メソッドにテーブル名を指定すると、新しいクエリビルダーを取得できます。
$builder = $db->table('users');
SELECT
$query = $builder->where('name !=', $name)
->where('id <', $id)
->orderBy('name', 'ASC')
->get();
foreach ($query->getResult() as $row) {
echo $row->title;
}
CodeIgniter3との違いは、テーブル名をビルダー生成時に指定することとと、メソッド名がcamelCaseに変わった程度です。
INSERT
insert()
メソッドを使います。
$data = [
'title' => 'My title',
'name' => 'My Name',
'date' => 'My date',
];
$builder->insert($data);
UPDATE
update()
メソッドを使います。
$data = [
'title' => $title,
'name' => $name,
'date' => $date,
];
$builder->where('id', $id);
$builder->update($data);
DELETE
delete()
メソッドを使います。
$builder->delete(['id' => $id]);
where()
メソッドでレコードを指定することもできます。
$builder->where('id', $id);
$builder->delete();
CodeIgniter\Model
以下のような機能があります。
- 自動データベース接続
- 基本的なCRUDメソッド
- 自動ページネーション
- 論理削除
データの検索
find()
プライマリーキーでレコードを検索します。
$user = $userModel->find($id);
$users = $userModel->find([1, 2, 3]);
findAll()
レコードを検索します。
$users = $userModel->findAll();
$users = $userModel->where('active', 1)->findAll();
$users = $userModel->findAll($limit, $offset);
データの保存
insert()
レコードを挿入します。
$data = [
'username' => 'darth',
'email' => 'd.vader@example.com',
];
$userModel->insert($data);
update()
プライマリーキーを指定してレコードを更新します。
$data = [
'username' => 'darth',
'email' => 'd.vader@example.com',
];
$userModel->update($id, $data);
$data = [
'active' => 1,
];
$userModel->update([1, 2, 3], $data);
WHERE句を指定してレコードを更新します。
$userModel->whereIn('id', [1, 2, 3])->set(['active' => 1])->update();
save()
プライマリーキーがない場合は挿入します。
$data = [
'username' => 'darth',
'email' => 'd.vader@example.com',
];
$userModel->save($data);
プライマリーキーがある場合は更新します。
$data = [
'id' => 3,
'username' => 'darth',
'email' => 'd.vader@example.com',
];
$userModel->save($data);
データの削除
delete()
プライマリーキーを指定してレコードを削除します。
$userModel->delete(12);
$userModel->delete([1, 2, 3]);
WHERE句を指定してレコードを削除します。
$userModel->where('id', 12)->delete();
Entityクラス
テーブルのレコードを表すクラスです。POPOではありません。使わなくても構いません。
app/Entities/User.php
<?php
namespace App\Entities;
use CodeIgniter\Entity\Entity;
class User extends Entity
{
// ...
}
CodeIgniter\Model
では、$returnType
プロパティに指定すると、検索結果がこのクラスのインスタンスになります。
protected $returnType = \App\Entities\User::class;
クエリビルダーでも getResult()
メソッドで指定すれば使えます。
$query->getResult(\App\Entities\User::class);
認証
ユーザガイドの 📕認証 に推奨事項が記載されています。
執筆時点で上記を満たす推奨できるパッケージは codeigniter4/shield と myth/auth 以外ありません。基本的に公式パッケージである codeigniter4/shield を使うことを推奨します。
セッション
以下でセッションオブジェクトが取得できます。
$session = session();
セッションの読み書き
書き込み
1アイテムを書き込む場合。
$session->set('some_name', 'some_value');
まとめて書き込む場合。
$newdata = [
'username' => 'johndoe',
'email' => 'johndoe@example.com',
'logged_in' => true,
];
$session->set($newdata);
読み込み
$session->get('some_name');
削除
1アイテムを削除する場合。
$session->remove('some_name');
まとめて削除する場合。
$items = ['username', 'email'];
$session->remove($items);
参考
Date: 2023/01/20