🔥

CodeIgniter 4 最速マスター

2021/12/25に公開

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/ にアクセスしてください。

ルーティング

📕URIルーティング

自動ルーティング

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/usersadmin/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()

$this->validate() を使います。

if ($this->request->getMethod() === 'post' && $this->validate([
    'title' => ['label' => 'タイトル', 'rules' => ['required', 'max_length[100]']],
    'body'  => ['label' => '本文', 'rules' => 'required'],
])) {
    // 検証パス
} else {
    // 検証エラー
}

検証するデータの指定

📕$this->validateData()

検証するデータを指定したい場合は、$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

📕RESTfulリソース処理

ルーティング

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

📕CodeIgniterのモデルの使用

以下のような機能があります。

  • 自動データベース接続
  • 基本的な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/shieldmyth/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