CodeIgniter 4 最速マスター
CodeIgniter Advent Calendar 2021
(最終更新:2022/10/24)
インストール&設定
インストール
Composerでインストールすると簡単です。
$ composer create-project codeigniter4/appstarter {フォルダ名}
フォルダ構成
CodeIgniter4のフォルダ構成は以下のようになっています。
ci4app/
├── app/ ... アプリケーション
│ ├── Common.php
│ ├── Config/ ... 設定
│ ├── Controllers/ ... コントローラ
│ ├── Database/ ... データベース
│ ├── Filters/ ... コントローラフィルタ
│ ├── Helpers/
│ ├── Language/
│ ├── Libraries/
│ ├── Models/ ... モデル
│ ├── ThirdParty/
│ └── 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から、セキュリティ上の理由で自動ルーティングはデフォルトではオフになります。
手動ルーティング
自動ルーティングをオフに
app/Config/Routes.php
$routes->setAutoRoute(false);
セキュリティ上の理由から、自動ルーティング(レガシー)は推奨しません。
できる限り、自動ルーティング(レガシー)は使用せず、「手動ルーティングのみ」または「自動ルーティング(改善)」を使いましょう。
HTTPメソッドでのルーティング
app/Config/Routes.php
にルートを設定します。
GETメソッドの場合は、$routes->get()
を使用します。
$routes->get('news', 'News::index');
上記は、http://example.com/news
にアクセスすると、News
コントローラの index()
メソッドが呼び出されます。
IDEでコントローラにジャンプしたい場合は、CodeIgniter v4.2.0から、以下の構文が使えます。
use App\Controllers\News;
$routes->get('news', [News::class, 'index']);
POSTメソッドの場合は、$routes->post()
を使用します。
$routes->post('news/create', 'News::create');
上記は、http://example.com/news/create
にアクセスすると、News
コントローラの create()
メソッドが呼び出されます。
URLの一部をキャプチャ
(:segment)
、(:any)
などのプレースホルダーを使います。
(:segment)
は1つのURIセグメント、(:any)
は任意の文字列にマッチします。
$routes->get('news/(:segment)', 'News::view/$1');
上記は、/news/foo
の場合に、News
コントローラの view()
メソッドに foo
を渡します。
グループ化
ルートをグループ化することもできます。
$routes->group('admin', function ($routes) {
$routes->get('users', 'Admin\Users::index');
$routes->get('blog', 'Admin\Blog::index');
});
上記は、admin/users
と admin/blog
のルートを設定しています。
ルートの確認
spark routes
コマンドでルートを確認できます。上に表示されたルートが優先されます。
$ php spark routes
コントローラ
コントローラの作成
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->validate()
を使います。
if ($this->request->getMethod() === 'post' && $this->validate([
'title' => ['label' => 'タイトル', 'rules' => ['required', 'max_length[100]']],
'body' => ['label' => '本文', 'rules' => 'required'],
])) {
// 検証パス
} else {
// 検証エラー
}
検証するデータの指定
検証するデータを指定したい場合は、$this->validateData()
を使います(v4.2.0以降)。
if ($this->request->getMethod() === 'post' && $this->validateData($data, $rule)) {
// 検証パス
} else {
// 検証エラー
}
エラーメッセージの上書き
$this->validate()
の第2引数にエラーメッセージを指定します。
if ($this->request->getMethod() === 'post' && $this->validate(
[
'title' => ['label' => 'タイトル', 'rules' => ['required', 'min_length[3]', 'max_length[255]']],
'body' => ['label' => '本文', 'rules' => 'required'],
],
[
'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;
}
}
リクエストパラメータの取得
$this->request->getPost()
、$this->request->getGet()
、$this->request->getJSON()
を使います。
$this->request->getPost('title')
上記は、POSTされた title
の値を取得します。
モデルの呼び出し
📕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');
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エスケープされます。
モデル
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');
$session->some_name
削除
1アイテムを削除する場合。
$session->remove('some_name');
まとめて削除する場合。
$items = ['username', 'email'];
$session->remove($items);
Discussion