SlimPHPのテンプレートエンジンとして、Twigを利用する手順をまとめておきます。
掲載したコードは Templates - Slim Framework のものを、SlimPHPのSkeletonプロジェクトで動くように書き換えたものです。
SlimPHPプロジェクトの作成
- composerはグローバルで動くものとする
- ターミナルを起動
- プロジェクトフォルダーを作りたいフォルダーに移動
- 以下でプロジェクトを作成(slim-twig-test フォルダーをプロジェクトフォルダーにする場合の例)
composer create-project slim/slim-skeleton slim-twig-test
cd slim-twig-test
composer require slim/twig-view
- 作成したフォルダー内に出来上がる composer.json をテキストエディタで開く
- "require" 欄から "slim/php-view" の行は不要なので削除して、上書き保存
- ターミナルで以下を実行して、インストール環境を更新する
composer update
設定ファイルを準備する
テンプレート用のパスと、Twigのオプションを設定します。PHPの組み込みサーバーで動作しているかどうかで、デバッグと本番設定を切り替えられるようにします。本番用は cache を利用し、デバッグ用は debug フラグをtrueにして、更新を監視するようにします。
- /src/settings.php を開く
- 以下のように修正
<?php
return [
'settings' => [
'displayErrorDetails' => true,
'view' => [
'template_path' => __DIR__ . '/../templates/',
'options' => [
'cache' => __DIR__ . '/../cache/'
]
],
'logger' => [
'name' => 'slim-app',
'path' => __DIR__ . '/../logs/app.log',
],
],
];
- PHPの組み込みサーバーで起動した時のテスト用の設定として、/srcフォルダー内に settings-debug.php を作成して、以下のようにする
<?php
return [
'settings' => [
'displayErrorDetails' => true,
'view' => [
'template_path' => __DIR__ . '/../templates/',
'options' => [
'debug' => true
]
],
'logger' => [
'name' => 'slim-app',
'path' => __DIR__ . '/../logs/app.log',
],
],
];
- 設定を読み込むために /public/index.php を開いて以下の通りにする
<?php
if (PHP_SAPI == 'cli-server') {
$file = __DIR__ . $_SERVER['REQUEST_URI'];
if (is_file($file)) {
return false;
}
$settings = require __DIR__ . '/../src/settings-debug.php';
}
else {
$settings = require __DIR__ . '/../src/settings.php';
}
require __DIR__ . '/../vendor/autoload.php';
session_start();
$app = new \Slim\App($settings);
require __DIR__ . '/../src/dependencies.php';
require __DIR__ . '/../src/middleware.php';
require __DIR__ . '/../src/routes.php';
$app->run();
コンテナにTwigを設定
SlimPHPのコンテナにTwigを追加します。
- /src/dependencies.php を開く
- 以下のようにする
<?php
$container = $app->getContainer();
$container['view'] = function ($c) {
$settings = $c->get('settings')['view'];
$view = new \Slim\Views\Twig(
$settings['template_path'],
$settings['options']
);
$view->addExtension(new \Slim\Views\TwigExtension(
$c['router'],
$c['request']->getUri()
));
return $view;
};
$container['logger'] = function ($c) {
$settings = $c->get('settings')['logger'];
$logger = new Monolog\Logger($settings['name']);
$logger->pushProcessor(new Monolog\Processor\UidProcessor());
$logger->pushHandler(new Monolog\Handler\StreamHandler($settings['path'], Monolog\Logger::DEBUG));
return $logger;
};
ルートを設定
リクエストに応じた処理を呼び出すルートを設定します。今回は、 http://0.0.0.0:8080/hello を呼び出すと、与えられた配列のユーザー一覧を表示して、 http://0.0.0.0:8080/hello/ユーザー名 とすると、指定したユーザーのプロフィールを表示するようにします。
- /src/routes.php を開いて、以下のようにする
<?php
$app->get('/hello', function($request, $response, $args) {
$users = [
'Tama',
'Kotta',
'Tanaka'
];
return $this->view->render($response, 'list.html', [
'list' => $users
]);
})->setName('list');
$app->get('/hello/{name}', function ($request, $response, $args) {
return $this->view->render($response, 'profile.html', [
'name' => $args['name']
]);
})->setName('profile');
/hello で呼び出された場合
- list.html をテンプレートに利用
- $users 配列に設定したデータを 'list' という名前でテンプレートエンジンに渡す
- /hello のパスを list という名前で記録しておく
/hello/{name} で呼び出された場合
- profile.html をテンプレートに利用
- パスの{name}の場所のデータを、 'name' という名前でテンプレートエンジンに渡す
- /hello/{name} のパスを profile という名前で記録しておく
テンプレートの作成
Twigのサンプルテンプレートを準備して、ルートに対応させます。
レイアウトテンプレートの作成
ユーザー一覧ページとプロフィールページのひな形となるレイアウト layout.html を作成します。
- /templates フォルダー内に layout.html を作成
- 以下のコードを書く
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>SlimPHP Twig Test-{% block title %}{% endblock %}</title>
</head>
<body>
<h1>{% block pagetitle %}{% endblock %}</h1>
<div id='content'>
{% block content %}
{% endblock %}
</div>
<hr />
<div id='footer'>
© Copyright 2016 by YuTanaka
</div>
</body>
</html>
- {% block <ブロック名> %}から{% endblock %}までの箇所を、他のテンプレートで指定した内容に差し替えることが可能
- 以下のようなブロックを定義している。list.htmlとprofile.htmlの {% block ・・・%} で囲んだ範囲が置きかわる
- title ブロック
- pagetitle ブロック
- content ブロック
ユーザー一覧ページ用のテンプレートの作成
- /templates フォルダー内に list.html を新規に作成
- 以下のTwigテンプレートコードを入力
{% extends "layout.html" %}
{% block title %}User List{% endblock %}
{% block pagetitle %}User List{% endblock %}
{% block content %}
<ul>
{% for item in list %}
<li><a href="{{ path_for('profile', {'name': item}) }}">{{item}}</a></li>
{% endfor %}
</ul>
{% endblock %}
- layout.html を継承することを宣言
- タイトルとページタイトルに User List を設定
- content ブロックに、ulタグを作成
- {% for item in list %} とすることで、 routes.php で list に渡した配列をループして、要素を item に入れて {% endfor %} との間をループ
- path_for()メソッドは、 slim/twig-view による拡張メソッド。解釈は以下の通り
- 第1引数に、ルート名を渡す。ルート名は routes.php のルート定義で->setName()したもの
- 第2引数に、ルートのプレースホルダーに対応するデータをオブジェクトで渡す
- この例では、クリックしたらプロファイルページを呼び出したいので、 profile のルートを指定して、'name'のプレースホルダーをループで取り出すitemに置き換える
- {{item}}とすると、itemの中身を表示
詳細ページ用のテンプレートの作成
- /templates フォルダー内に profie.html を新規に作成
- 以下のTwigテンプレートコードを入力
{% extends "layout.html" %}
{% block title %}Profile{% endblock %}
{% block pagetitle %}{{name}}'s Profile{% endblock %}
{% block content %}
<p>これは「{{name}}」のプロフィールです。</p>
<p><a href="{{ path_for('list') }}">一覧へ</a></p>
{% endblock %}
- layout.html を継承することを宣言
- タイトルにProfileを設定
- ページタイトルに、渡された name プロパティと、続けて 's Profile を設定
- content ブロックでは、「name プロパティのプロフィールです。」と表示する段落と、一覧に戻るリンクを設定
- 一覧へ戻るためのリンクは、listのルートをそのまま使う
テスト
準備ができたら、PHPの組み込みサーバーを起動して、動作を確認します。
php -S 0.0.0.0:8080 -t public public/index.php