お問い合わせ

ブログ

これまでに経験してきたプロジェクトで気になる技術の情報を紹介していきます。

DockerでCodeigniter4 betaを動かす

Kitaru Kitaru 4 years
DockerでCodeigniter4 betaを動かす

CodeIgniter3はシンプルな作りでカスタマイズしやすく、しかもとても速く動作します。
そういう理由から、ソーシャルゲームの案件でも使用しているのですが、 後発のLaravelやCakephp3と比べるとどうしても古臭いと感じてしまう時があります。

そこでCodeIgniter3の代わりになるような軽量なPHPフレームワークがないか調べてみたら、 2019年3月にCodeIgniter4のベータ版がリリースされており、 ドキュメントも整備されているようなので、少し触ってみることにしました。

Dockerのインストール

CentOS 7.6にDockerをインストールしてCodeIgniter4が動く環境を構築します。

    # cat /etc/redhat-release 
    CentOS Linux release 7.6.1810 (Core) 

    # yum install -y yum-utils device-mapper-persistent-data lvm2
    # yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    # yum -y install docker-ce
    # systemctl start docker
    # docker --version
    Docker version 18.09.6, build 481bc77156
    # systemctl enable docker

一般ユーザがsudoなしでdockerコマンドを実行できるようにdockerグループに所属させます。 なお、もし一般ユーザがログインしている場合は、一度ログアウトしてログインし直す必要があります。

    # gpasswd -a (一般ユーザ) docker

Docker Composeのインストール

復数のコンテナをまとめて管理するために、Docker Composeもインストールします。

    # curl -L https://github.com/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
    # chmod +x /usr/local/bin/docker-compose
    # docker-compose --version
    docker-compose version 1.24.0, build 0aa59064

Dockerの構成

    ~/ci4_project
     ├── docker-compose.yml
     ├── mysql
     │       └── my.cnf
     ├── nginx
     │       └── default.conf
     ├── php-fpm
     │       ├── Dockerfile
     │       └── php.ini
     └── src   <- この下にCodeigniter4のソースを設置します。

docker-compose.yml

    version: '3'
    services:
      nginx:
        image: nginx
        restart: always
        ports:
          - 80:80
        volumes:
          - ./src:/var/www/html
          - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
        depends_on:
          - php-fpm
      php-fpm:
        build: ./php-fpm
        restart: always
        volumes:
          - ./src:/var/www/html
          - ./php-fpm/php.ini:/usr/local/etc/php/php.ini
        depends_on:
          - mysql
          - redis
      mysql:
        image: mysql:5.7
        restart: always
        ports:
          - 3306:3306
        environment:
          MYSQL_ROOT_PASSWORD: root001
          TZ: "Asia/Tokyo"
        volumes:
          - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
          - mysql-storage:/var/lib/mysql
      redis:
        image: redis:4
        restart: always
        ports:
          - 6379:6379
        volumes:
          - redis-storage:/data
    volumes:
      mysql-storage:
      redis-storage:

mysql/my.cnf

    [mysqld]
    character-set-server=utf8

    [client]
    default-character-set=utf8

nginx/default.conf

    server {
        listen       80;
        server_name  localhost;
        root         /var/www/html;
        index        index.php;

        access_log /var/log/nginx/access.log;
        error_log  /var/log/nginx/error.log;

        location / {
            try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ \.php$ {
            fastcgi_pass php-fpm:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }
    }

php-fpm/Dockerfile

    FROM php:7.3-fpm

    ENV COMPOSER_ALLOW_SUPERUSER 1

    # apcuとopcacheはインストールしなくても問題ありません。
    RUN apt-get update && \
        apt-get -y install libxml2-dev libcurl4-openssl-dev zip unzip git && \
        apt-get clean && \
        rm -rf /var/lib/apt/lists/* && \
        docker-php-ext-configure mysqli --with-mysqli=mysqlnd && \
        docker-php-ext-install intl json mbstring mysqli xml curl opcache && \
        pecl install redis apcu && \
        docker-php-ext-enable redis apcu && \
        curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

■2020.04.04追記
Dockerfileの「FROM php:7.3-fpm」を「FROM php:7.4-fpm」に変更した場合は、docker-compose upの時に次のようなエラーメッセージ(鬼車がない)が表示されます。

    ・・・
    checking for oniguruma... no
    configure: error: Package requirements (oniguruma) were not met:

    No package 'oniguruma' found
    ・・・

その場合はDockerfileを次のように修正して下さい。

    ■修正前
    apt-get -y install libxml2-dev libcurl4-openssl-dev zip unzip git && \

    ■修正後
    apt-get -y install libxml2-dev libcurl4-openssl-dev libonig-dev zip unzip git && \

php-fpm/php.ini

    [Date]
    date.timezone = "Asia/Tokyo"

    [mbstring]
    mbstring.internal_encoding = UTF-8
    mbstring.language = Japanese

Dockerコンテナの起動

    $ cd ~/ci4_project
    $ docker-compose up -d
    ・・・
    $ docker-compose ps
            Name                       Command               State                 Ports              
    --------------------------------------------------------------------------------------------------
    ci4_project_mysql_1     docker-entrypoint.sh mysqld      Up      0.0.0.0:3306->3306/tcp, 33060/tcp
    ci4_project_nginx_1     nginx -g daemon off;             Up      0.0.0.0:80->80/tcp               
    ci4_project_php-fpm_1   docker-php-entrypoint php-fpm    Up      9000/tcp                         
    ci4_project_redis_1     docker-entrypoint.sh redis ...   Up      0.0.0.0:6379->6379/tcp

4つのコンテナのStateが全てUpになっていたらOKです。

CodeIgniter4のインストール

php-fpmコンテナの中に入って、Composerを使用してCodeigniter4をインストールします。

    $ docker-compose exec php-fpm /bin/bash
    # composer create-project codeigniter4/framework:v4.0.0-beta.3 ci4
    ・・・
    # exit

作成したCodeigniter4のプロジェクトの所有者はrootになっており、そのままだと扱いにくいので一般ユーザに変更します。

    $ su -
    # cd ~(一般ユーザ)/ci4_project/src
    # chown -R (一般ユーザ):(一般ユーザ) ci4
    # exit

Webサーバがwritableディレクトリの中にキャッシュやログなどのファイルを作成するため、パーミッションを変更します。

    $ cd ~/ci4_project/src
    $ chmod -R 777 ci4/writable

srcディレクトリの直下にpublic/index.phpのシンボリックリンクを作成します。
こうすることによってhttp://192.168.56.101/ci4/public/ ではなく、http://192.168.56.101/ でもアクセスできるようになります。
※ 以降、IPの部分は自分の環境にあわせて適宜置き換えてください。

    $ ln -s ci4/public/index.php index.php

CodeIgniter4のサンプル

Debug Toolbar

CodeIgniter3では開発中にプロファイラ機能を使用してクエリの内容や実行時間を見ていましたが、 CodeIgniter4ではDebug Toolbarというものを利用するようです。まずはこれを使ってみたいと思います。

.envファイル

Codeigniter4のプロジェクトの直下にenvファイルがあり、これをコピーしてenvファイルと同階層に.envファイルを作成します。
そして.envの17行目を次のように修正します。

    # CI_ENVIRONMENT = production
    ↓
    CI_ENVIRONMENT = development

CI_ENVIRONMENTにはproduction、development、testingが定義できますが、 Debug Toolbarはdevelopmentではないと表示されません。

app/Config/App.php

App.phpの24行目を次のように修正します。

    public $baseURL = 'http://localhost:8080';
    ↓
    public $baseURL = 'http://192.168.56.101';

画面に表示されるDebug Toolbarをソースで確認すると

    

というコードになっており、このsrc属性に$baseURLの値が使用されています。

以上の設定を行ってhttp://192.168.56.101/ にアクセスすると、画面右下に炎上?のアイコンが表示されており、これをクリックすると次のようなパネルが表示されます。

Debug Toolbar



リードスルー

次はRedisを参照してデータが存在しない場合はMySQLからデータを読み込むサンプルを作ります。

MySQL

まず準備としてMySQLにデータベースとテーブル、初期データを作成します。

    $ docker-compose exec mysql /bin/bash
    # mysql -u root -p
    Enter password: ← root001を入力します。
    ・・・
    mysql> CREATE DATABASE ci4_db;
    mysql> use ci4_db;
    mysql> CREATE TABLE `users` (
        -> `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        -> `user_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
        -> `name` VARCHAR(32) NULL DEFAULT NULL,
        -> `age` INT(10) UNSIGNED NULL DEFAULT NULL,
        -> PRIMARY KEY (`id`),
        -> UNIQUE INDEX `user_id` (`user_id`)
        -> )
        -> COLLATE='utf8_general_ci'
        -> ENGINE=INNODB
        -> ;
    mysql> INSERT INTO `ci4_db`.`users` (`user_id`, `name`, `age`) VALUES (100, '屋代駿介', 35),(101, '須加友枝', 29),(102, '永来一八', 15),(103, '荷宮知愛', NULL);
    mysql> SELECT * FROM users;
    +----+---------+--------------+------+
    | id | user_id | name         | age  |
    +----+---------+--------------+------+
    |  1 |     100 | 屋代駿介     |   35 |
    |  2 |     101 | 須加友枝     |   29 |
    |  3 |     102 | 永来一八     |   15 |
    |  4 |     103 | 荷宮知愛     | NULL |
    +----+---------+--------------+------+
    4 rows in set (0.00 sec)
    mysql> exit;
    # exit
app\Config\Database.php

MySQLの接続先をmysqlコンテナに変更します。

    public $default = [
        'DSN'      => '',
        'hostname' => 'mysql',     // 修正する
        'username' => 'root',      // 修正する
        'password' => 'root001',   // 修正する
        'database' => 'ci4_db',    // 修正する
        'DBDriver' => 'MySQLi',
        'DBPrefix' => '',
        'pConnect' => false,
        'DBDebug'  => (ENVIRONMENT !== 'production'),
        'cacheOn'  => false,
        'cacheDir' => '',
        'charset'  => 'utf8',
        'DBCollat' => 'utf8_general_ci',
        'swapPre'  => '',
        'encrypt'  => false,
        'compress' => false,
        'strictOn' => false,
        'failover' => [],
        'port'     => 3306,
    ];
app\Config\Cache.php

キャッシュのデフォルトの書き込み先がファイルになっているのでRedisにして、 Redisの接続先をredisコンテナに変更します。

    public $handler = 'file';
    ↓
    public $handler = 'redis';
    public $redis = [
        'host'     => 'redis',    // 修正する
        'password' => null,
        'port'     => 6379,
        'timeout'  => 0,
        'database' => 0,
    ];
app/Entities/User.php

usersテーブルのレコードを保存するエンティティを作成します。 また、Entitiesディレクトリも存在しないため一緒に作成する必要があります。

エンティティはCodeIgniter\Entityクラスを継承する必要があります。
エンティティにはテーブルのカラムと対応したプロパティを定義します。
テーブルから取得した値は文字列としてプロパティに設定されるため、整数として扱いたい場合は$_optionsの中でキャストの設定を行う必要があります。
もしカラムがNullableの場合は?integerのようにキャストの型の前に?をつける必要があります。?がないとnullは参照時に0として扱われます。

   [
                 'id'           => 'integer',
                 'user_id'      => 'integer',
                 'age'          => '?integer',
             ],
             'dates'   => [],
         ];
     }
app/Models/UserModel.php

usersテーブルを操作するためのモデルを作成します。

モデルはCodeIgniter\Modelクラスを継承する必要があります。
Modelには多くのプロパティがありますが、ここではモデルが扱うテーブルの名前と、結果データの型の2つのみを定義しています。

  
app/Controllers/User.php

最後にコントローラを作成します。

コントローラはApp\Controllers\BaseControllerクラスを継承する必要があります。
モデルは$this->load->modelではなく、普通のクラスのようにnewでインスタンスを生成して使用します。
モデルメソッドの使い方はCodeigniter3とほぼ同じですが、firstメソッドの戻り値は、UserModelモデルで定義したとおりUserエンティティになっています。

キャッシュの読み込みはcache(キー名)、キャッシュの書き込みはcache()->save(キー名, 値, 生存期間(秒))で行います。

  where('user_id', (int) $userId)->first();    // 指定されたuser_idのレコードが存在しない場合はnullが返る

                cache()->save($userId, $user, 600);
            }

            d($user);
            d($user->id);
            d($user->user_id);
            d($user->name);
            d($user->age);
        }
    }

以上の修正を行ってからhttp://192.168.56.101/user/index/103/ にアクセスすると、次のような画面が表示されます。

Debug Toolbar2



なお、http://192.168.56.101/user/index/104/ のようにusersテーブルに存在しないuser_idを指定するとスタックトレースが表示されます。
これはfirstメソッドの戻り値がnullであるにも関わず、プロパティを参照しようとしているためです。

Debug Toolbar3
DockerでCodeigniter4 betaを動かす 2021-08-24 12:30:08

コメントはありません。

4816

お気軽に
お問い合わせください。

お問い合わせ
gomibako@aska-ltd.jp