グローバルナビゲーションへ

本文へ

フッターへ

お役立ち情報Blog



CodeIgniter3にTwigを連携して使う

アーティスではシステム開発にPHPのフレームワークであるCodeIgniterを使うことがあります。
また、PHPのテンプレートエンジンであるTwigを導入することもあります。今回はこの2つを連携して使っていきたいと思います。

本記事での筆者の環境

  • PHP 5.6.40
  • CodeIgniter 3.1.11
  • Twig 1.42.5

使ったことがない方のために少しだけご紹介

CodeIgniter
https://codeigniter.com/

  • MVCアーキテクチャを推奨しているPHPフレームワークです。
    CodeIgniter encourages MVC, but does not force it on you. 
  • Documentが日本語対応しています。
Twig
https://twig.symfony.com/

  • PHPのテンプレートエンジンです。
    Twig is a modern template engine for PHP
このコードを

<?php echo $var ?>
<?php echo htmlspecialchars($var, ENT_QUOTES, 'UTF-8') ?>

この様に書くことができるので書きやすさが違うのがわかるかと思います。

{{ var }}
{{ var|escape }}

連携する

テスト用にまず下記機能のフォームを作りました。
まだTwigは導入していないのでviewは素のPHPで書いています。

  • 名前を入力してpostすると返答が表示される
  • 空欄のままpostするとエラーを表示する
<?php
// controllers/Test.php

Class Test extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->load->helper(['url', 'form']);
        $this->load->library('form_validation');
    }

    public function index()
    {
        $data['message'] = 'Input your name!';

        // POSTだったら
        if ($this->input->method() === 'post') {
            // お名前が入力されているかチェック
            $this->form_validation->set_rules('name', 'name', 'required');
            $this->form_validation->set_error_delimiters('<p style="color: red;">', '</p>');
            $this->form_validation->run();
        }

        $this->load->view('input.php', $data);
    }
}
<!DOCTYPE html>
<!-- views/input.php -->
<html>
    <head>
        <title>Twig連携テスト</title>
    </head>
    <body>
        <!-- エラーがあったら表示する -->
        <?php echo form_error('name'); ?>

        <!-- 入力フォーム -->
        <form action="<?php echo base_url(). 'test/'; ?>" method="post">
            <p><?php echo $message; ?></p>
            <input type="text" name="name" value="<?php echo set_value('name'); ?>">
            <button type="submit">post</button>
        </form>

        <!-- 入力があったら表示する -->
        <?php if (set_value('name')) { ?>
        <p>Hello! <?php echo set_value('name'); ?>!!</p>
        <?php } ?>
    </body>
</html>

Twigをcomposerでインストール

CodeIgniterのapplicationディレクトリ内にcomposerでTwigをインストールします。
applicationディレクトリ内にcomposer.jsonファイルを設置します。

{
    "require": {
        "twig/twig": "1.42.5"
    }
}
 composer install コマンドでインストールします。

$ composer install
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 2 installs, 0 updates, 0 removals
  - Installing symfony/polyfill-ctype (v1.17.1): Loading from cache
  - Installing twig/twig (v1.42.5): Loading from cache
Writing lock file
Generating autoload files
1 package you are using is looking for funding.
Use the `composer fund` command to find out more!

CodeIgniterの設定

 config/config.php でComposer auto-loadingを TRUE にします。

/*
|--------------------------------------------------------------------------
| Composer auto-loading
|--------------------------------------------------------------------------
|
| Enabling this setting will tell CodeIgniter to look for a Composer
| package auto-loader script in application/vendor/autoload.php.
|
|       $config['composer_autoload'] = TRUE;
|
| Or if you have your vendor/ directory located somewhere else, you
| can opt to set a specific path as well:
|
|       $config['composer_autoload'] = '/path/to/vendor/autoload.php';
|
| For more information about Composer, please visit http://getcomposer.org/
|
| Note: This will NOT disable or override the CodeIgniter-specific
|       autoloading (application/config/autoload.php)
*/
$config['composer_autoload'] = TRUE;

CodeIgniterにTwigライブラリを作成

 controllers/Test.php に直接Twigの読み込みを記載してもよいのですが、使い回しできるようにライブラリを作成します。

<?php
// libraries/Twig.php

class Twig
{
    private $ci;
    private $twig;

    public function __construct()
    {
        // CodeIgniterのインスタンスを取得
        $this->ci =& get_instance();

        // Twigをnew
        $loader = new Twig_Loader_Filesystem(VIEWPATH);
        $this->twig = new Twig_Environment($loader);

        // CodeIgniterのhelper関数をTwigに追加することもできる
        $this->twig->addGlobal('baseUrl', base_url());
        $this->twig->addFunction(new Twig\TwigFunction('setValue', 'set_value'));
        $this->twig->addFunction(new Twig\TwigFunction('formError', 'form_error'));
    }

    // CodeIgniterのoutputにTwigのrenderを渡す
    public function out($template, $data=[])
    {
        $this->ci->output->set_output(
            $this->twig->render($template, $data)
        );
    }
}

Twigライブラリを読み込んで使う

 controllers/Test.php でTwigライブラリを読み込んで使います。

$ git diff controllers/Test.php
diff --git a/application/controllers/Test.php b/application/controllers/Test.php
index 46f8a05..d1665df 100644
--- a/application/controllers/Test.php
+++ b/application/controllers/Test.php
@@ -7,7 +7,7 @@ Class Test extends CI_Controller
     {
         parent::__construct();
         $this->load->helper(['url', 'form']);
-        $this->load->library('form_validation');
+        $this->load->library(['twig', 'form_validation']);
     }

     public function index()
@@ -21,6 +21,6 @@ Class Test extends CI_Controller
             $this->form_validation->run();
         }

-        $this->load->view('test.php', $data);
+        $this->twig->out('test.html.twig', $data);
     }
 }
 views/test.php の変数部分をTwigの記法に変更した  views/test.html.twig ファイルを作成します。

<!DOCTYPE html>
<!-- views/test.html.twig -->
<html>
    <head>
        <title>Twig連携テスト</title>
    </head>
    <body>
        <!-- エラーがあったら表示する -->
        {{ formError('name')|raw }}

        <!-- 入力フォーム -->
        <form action="{{ baseUrl }}test/" method="post">
            <p>{{ message }}</p>
            <input type="text" name="name" value="{{ setValue('name') }}">
            <button type="submit">post</button>
        </form>

        <!-- 入力があったら表示する -->
        {% if setValue('name') is not empty %}
            <p>Hello! {{ setValue('name') }}!!</p>
        {% endif %}
    </body>
</html>

動作確認

以上でCodeIgniterとTwigを連携して使うことができました。
viewファイルが素のPHPよりスッキリして見通しも良いかと思います。

おまけ:PHP5.6環境でTwig1系の最新を指定していたら急にエラーが出るようになった話

本記事ではcomposer.jsonのTwigのバージョンを 1.42.5 に明示的に指定していますが、過去の案件では1系の最新バージョンをインストールするように指定していました。

{
    "require": {
        "twig/twig": "1.*"
    }
}

2020/7/8に新たにCodeIgniterとTwigを使用してプロジェクトを作成しようとした際に画像のようなエラーが表示されました。

直近の案件の同構成プロジェクトのcomposer.jsonやCodeIgniter内のコードを確認しましたが、差分がなかったのでエラーの箇所を確認することに。

// 該当箇所のコード
class ModuleNode extends Node
{
    public function __construct(\Twig_NodeInterface $body, ?AbstractExpression $parent, \Twig_NodeInterface $blocks, \Twig_NodeInterface $macros, \Twig_NodeInterface $traits, $embeddedTemplates, $name, $source = '')
    {
        if (!$name instanceof Source) {
            @trigger_error(sprintf('Passing a string as the $name argument of %s() is deprecated since version 1.27. Pass a \Twig\Source instance instead.', __METHOD__), E_USER_DEPRECATED);
            $source = new Source($source, $name);
        } else {
 ?AbstractExpression この変数にPHP7.1で実装されたnull許容型宣言が使用されていたのでcomposerのサイトを確認。

2020年7月5日に v1.43.0 がリリースされ、PHPの下限バージョンが 7.1.3 に上がっていました。

また、筆者はPHP7.4環境にDockerでPHP5.6環境を構築し開発しており、HOST側でcomposer installを実行してしまったため、 v1.43.0 がインストールされてしまいました。

対応策

  • composer.jsonでTwigのバージョンを明示的に指定する
  • PHP5.6環境でcomposer installを実行する
  • プラットフォームで使用するPHPのバージョンを明示的に指定する
  {
    ...
    "config": {
      "platform": {
        "php": "5.6"
      }
    }
  }

外部のパッケージを使う際、何も考えず過去プロジェクトの設定ファイルを参照すると思わぬ落とし穴があるなと学びました。。

さいごに

今回はCodeIgniter3とTwigを連携して使う方法を、簡単なフォームを作りながらご紹介しました。

素のPHPで書くより感覚的に書くことができるので、効率も上がるのでは無いかと思います。 ぜひ、CodeIgniterとTwigを使ってアプリケーションを開発してみてください。

Twig v1.xのドキュメントはこちら

この記事を書いた人

ばね
ばねソリューション事業部 システムエンジニア
東京で2年半エンジニアとしての経験を積み、浜松にUターンの後、アーティスへ入社。
ソリューション事業部のWebエンジニアとして、システムの設計・開発・保守・運用からインフラまで幅広く従事している。
フルスタックエンジニア目指して現在も勉強の日々。車が好き。
この記事のカテゴリ

FOLLOW US

最新の情報をお届けします