前回FOSUserBundleのインストールとセットアップを行いました。 セットアップが完了していれば画面が表示されるはずです。
動作確認
ログインページを表示してみます。 http://localhost:8000/login
画面が寂しいですが、一応表示されますね。
ログインしてみたいのでユーザーを作ってみましょう。
ユーザーを作成
登録画面から登録してもよいですが、確認メール送信の為にsmtpの設定やらが必要なのでコンソールから作ります。
php app/console list fos
FOSUserBundleのコマンドが増えている事が確認できます。
fos:user:create
でユーザーが作れるので作ってみます。
$ fos:user:create
Please choose a username:quartet
Please choose an email:quqrtet@example.com
Please choose a password:
Created user quartet
ユーザーが作成できたらログイン等を確認してみましょう。
ログインできていたら、Symfony Profiler Toolbar に認証情報が表示されます。
レイアウトを変更する
インストールしたバンドルのレイアウトを修正したい!
直接インストールしたバンドルを修正するなんてのは論外です。
なのでそんな時にどうしたらよいかの説明をします。
基本的な流れはこれだけです。
- サードパーティーバンドルが使用している ビューのファイル名 を確認する。
- 同じビューのファイル名のテンプレートを サブバンドル 内に作る。
- 作ったテンプレートを編集
サブバンドル って何?となりますが、バンドルには親子関係を設定できます。
要は、 QuartetBlogBundleの親がFOSUserBundleである事を定義 すればよいのです。
クラスの継承関係みたいなもんですね。
バンドルの親子関係を定義
早速定義してみます。
<?php
// QuartetBlogBundle
namespace Quartet\Bundle\BlogBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class QuartetBlogBundle extends Bundle
{
public function getParent()
{
return 'FOSUserBundle';
}
}
バンドルの親子関係の定義はこれだけです。
次にレイアウトをオーバーライドしてみます。
レイアウトのオーバーライド
プログラムでもオーバーライドする時は親メソッド名が分かっていないとできません。
感覚的にはそんな感じです。
今回はユーザー情報ページを変更してみようと思います。
http://localhost:8000/profile/
まずは、 このページがどのテンプレートファイルを使っているか を知る必要があります。
探してみる
下のコマンドで、どのアクションを実行しているかが分かるので、そこからvendorディレクトリ内のテンプレートファイルを探します。
php app/console debug:router {ルーティング名}
こんな事をしなくても、バンドルのディレクトリ構成は一緒なのでResources/views
の中を見れば大体察しがつく事が殆どですが笑
下記がユーザー情報ページのテンプレートです。
// Resources/views/Profile/show.html.twig
{% extends "FOSUserBundle::layout.html.twig" %}
{% block fos_user_content %}
{% include "FOSUserBundle:Profile:show_content.html.twig" %}
{% endblock fos_user_content %}
テンプレート FOSUserBundle::layout.html.twig を継承している事が分かります。
補足: twig テンプレート内のファイルパス
twig内のファイルパスの命名規則は
バンドル名:ディレクトリ名:テンプレートファイル名
となっています。
twig内のファイルパスは、各バンドルのResources/views/
からの絶対ファイルパスになります。Resources/views/ディレクトリ名/テンプレートファイル名
といった感じです。
FOSUserBundle::layout.html.twig
の様なパスはディレクトリに入っていない事を意味します。
下記がそのテンプレートファイルの中身です。
// Resouces/views/layout.html.twig
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<div>
{% if is_granted("IS_AUTHENTICATED_REMEMBERED") %}
{{ 'layout.logged_in_as'|trans({'%username%': app.user.username}, 'FOSUserBundle') }} |
<a href="{{ path('fos_user_security_logout') }}">
{{ 'layout.logout'|trans({}, 'FOSUserBundle') }}
</a>
{% else %}
<a href="{{ path('fos_user_security_login') }}">{{ 'layout.login'|trans({}, 'FOSUserBundle') }}</a>
{% endif %}
</div>
{% if app.request.hasPreviousSession %}
{% for type, messages in app.session.flashbag.all() %}
{% for message in messages %}
<div class="flash-{{ type }}">
{{ message }}
</div>
{% endfor %}
{% endfor %}
{% endif %}
<div>
{% block fos_user_content %}
{% endblock fos_user_content %}
</div>
</body>
</html>
このテンプレートファイルを、子バンドルであるQuartetBlogBundle
の同じテンプレートファイルパスにコピーします。
場所はQuartetBlogBundle::layout.html.twig
です。
コピーしたあとのテンプレートを編集すると、レイアウトが変更される事が確認できると思います。
twigテンプレート内の{% block %}の補足
twigのテンプレートを見ていると、{% block block_name %}{% endblock %}
の記述が至るとこに見られます。
これがテンプレートの継承の仕組みです。
感覚的にはプログラムのクラスメソッドにかなり近いです。
下に例を書きます。
基本その1
// layout.html.twig
<html>
{% block content %}
hello world!
{% endblock %}
</html>
これをレンダリングすると、<html>hello world!</html>
と表示されます。
基本その2 ~ 継承編 ~
レイアウトを使うテンプレートを作ってみます。
// view.html.twig
{% extends '::layout.html.twig' %}
{% block content %}
hello twig!
{% endblock %}
これをレンダリングすると、<html>hello twig!</html>
と表示されます。
動作はメソッドオーバーライドと同じです。
クラスで表すとこんな感じです。
<?php
class Layout
{
public function content()
{
return 'hello world!';
}
}
class View extends Layout
{
public function content()
{
return 'hello twig!';
}
}
echo (new View())->content(); // => 'hello twig!'
基本その3 ~ 継承その2編 ~
クラスメソッドに近いのなら、親クラスのメソッドも呼べるの?
答えは YES
view.html.twigを少し変えます。
// view.html.twig
{% extends '::layout.html.twig' %}
{% block content %}
{{ parent() }} hello twig!
{% endblock %}
大体想像付きますが、これをレンダリングすると <html>hello world! hello twig!</html>
となります。
もちろん {{ parent() }}
の位置はどこにでも置けます。
// view.html.twig
{% extends '::layout.html.twig' %}
{% block content %}
hello {{ parent() }} twig!
{% endblock %}
これもクラスで表すとこんな感じです。
<?php
class Layout
{
public function content()
{
return 'hello world!';
}
}
class View extends Layout
{
public function content()
{
return parent::content() . 'hello twig!';
}
}
echo (new View())->content(); // => 'hello world! hello twig!'
他にもFOSUserBundleの拡張はたくさん
全ては書けないのでとりあえず列挙しておきます。
- Hooking into the controllers
- Overriding Default FOSUserBundle Controllers
- Overriding Default FOSUserBundle Forms
- About FOSUserBundle User Manager
- FOSUserBundle Command Line Tools
- Logging by Username or Email
- The username Form Type
- FOSUserBundle Emails
- Using Groups With FOSUserBundle
- More about Doctrine implementations
- Overriding Default FOSUserBundle Validation
- FOSUserBundle Canonicalization
- Using a custom storage layer
- Advanced routing configuration
- FOSUserBundle Configuration Reference
- FOSUserBundle Invitation