phalconのview(voltエンジン)


voltエンジン

Volt は、PHPのためにCで記述されており、とても速く、デザイナにも扱いやすいテンプレート言語です。簡単にビューを書けるようにヘルパーセットも提供されており、また、Phalcon の他のコンポーネントに高度に統合されているので、コーディング量も少なく使い勝手はいいと思います。voltで書かれたコードは初回読み込み時にキャッシュとして、phpファイルにコンパイルされます。phalcon volt ドキュメントより抜粋。

voltの有効化

サービスコンテナの設定時に:$di = new Phalcon\DI\FactoryDefault();

use Phalcon\Mvc\View;

// Voltをテンプレートエンジンとして登録する
$di->set('view', function () {

    $view = new View();

    $view->setViewsDir('../app/views/');

    $view->registerEngines(
        array(
            ".volt" => 'Phalcon\Mvc\View\Engine\Volt'
        )
    );

    return $view;
});

コントローラからビューへのデータ設定

MVCモデルではデータの取得や加工等をコントローラで行いコントローラからビューへデータを渡す必要があります。
Phalconでは以下のように2通りの書き方があります。

コントローラのアクション内で

//例えばモデルPostから取得したデータをビューへ受け渡す場合
$post = Post::findFirst();

$this->view->post = $post;
//または
$this->view->setVar("post", $post);

//もちろん変数でなくても
$this->view->name = "テスト";
//または
$this->view->setVar("name", "テスト");

コントローラからセットした変数($this->view->post or $this->view->setVar(“post”, ????))をビューで利用するためには

{{ post }}

でOKです。

voltの表記

設定した変数や文字を出力する場合、{{}}

{{ post }}

制御分を扱う場合、{% %}

{% if a==b %}
{% endif %}

といった感じになります。phpで書くよりコーディング量は減りますね

制御文

よく利用する制御文の利用方法と解説

変数

変数postの属性にアクセスする
voltの場合

{{ post.title }}

phpの場合

$post->title

変数postが配列のときのアクセス
voltの場合

{{ post['title'] }}

phpの場合

$post['title']

if文

if文の書き方
voltの場合

{% set a = 1 %}
{% if a === 1 %}
OK
{% else %}
ELSE
{% endif %}

コンパイル後のphp

<?php $a = 1; ?>
<?php if ($a === 1) { ?>
OK
<?php } else { ?>
ELSE
<?php } ?>

ループ

単純なループ
voltのforはforeachにコンパイルされます。
voltの場合

{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}

{% for value in numbers %}
  Value: {{ value }}
{% endfor %}

コンパイル後のphp

<?php $numbers = array('one' => 1, 'two' => 2, 'three' => 3); ?>

<?php foreach ($numbers as $value) { ?>
  Value: <?php echo $value; ?>
<?php } ?>

keyとvalueの扱い
voltの場合

{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}

{% for name, value in numbers %}
  Name: {{ name }} Value: {{ value }}
{% endfor %}

コンパイル後のphp

<?php $numbers = array('one' => 1, 'two' => 2, 'three' => 3); ?>

<?php foreach ($numbers as $name => $value) { ?>
  Name: <?php echo $name; ?> Value: <?php echo $value; ?>
<?php } ?>

for文とifを同時に書く。ループに条件をつけることができます。
コンパイル後のphpをみるとforeachの直下にif文が入っていることが分かります。
voltの場合

{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}

{% for value in numbers if value < 2 %}
  Value: {{ value }}
{% endfor %}

コンパイル後のphp

<?php $numbers = array('one' => 1, 'two' => 2, 'three' => 3); ?>

<?php foreach ($numbers as $value) { if ($value < 2) { ?>
  Value: <?php echo $value; ?>
<?php } ?><?php } ?>

もちろん、「break」と「continue」があります。ループから抜けたり、現在のブロック内で強制的に次のイテレーションへ移ったりすることができます。
voltの場合

{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}

{% for index, value in numbers %}
    {% if index is even %}
        {% continue %}
    {% else %}
    	{% break %}
    {% endif %}
    ...
{% endfor %}

コンパイル後のphp

<?php $numbers = array('one' => 1, 'two' => 2, 'three' => 3); ?>

<?php foreach ($numbers as $index => $value) { ?>
    <?php if (((($index) % 2) == 0)) { ?>
        <?php continue; ?>
    <?php } else { ?>
    	<?php break; ?>
    <?php } ?>
    ...
<?php } ?>

この中で利用している「{% if index is even %}」については後ほど解説します。

ループの特別な変数

loop.index
ループ中、現在のイテレーションが何番目かを返す(順番は1からスタート)
loop.index0
ループ中、現在のイテレーションが何番目かを返す(順番は0からスタート)
loop.revindex
ループ中、現在のイテレーションがループの最後から何番目かを返す(順番は1からスタート)
loop.revindex0
ループ中、現在のイテレーションがループの最後から何番目かを返す(順番は0からスタート)
loop.first
ループの最初のイテレーションであれば、(boolean)trueを返す
loop.last
ループの最後のイテレーションであれば、(boolean)trueを返す
loop.length
ループの要素数を返す

実際にコーディングし、その結果を記載します。

{% set numbers = ['one', 'two', 'three','four'] %}

{% for index, value in numbers %}
	{% if loop.first %}
    	最初<br>
    	loop.length:{{ loop.length }}<br>
    {% endif %}
    {% if loop.last %}
    	最後<br>
    {% endif %}
    value:{{ value }}<br>
    loop.index:{{ loop.index }}<br>
    loop.index0:{{ loop.index0 }}<br>
    loop.revindex:{{ loop.revindex }}<br>
    loop.revindex0:{{ loop.revindex0 }}<br>
{% endfor %}

実行結果は

/*** 1週目 ***/
最初
loop.length:4
value:one
loop.index:1
loop.index0:0
loop.revindex:4
loop.revindex0:3
/*** 2週目 ***/
value:two
loop.index:2
loop.index0:1
loop.revindex:3
loop.revindex0:2
/*** 3週目 ***/
value:three
loop.index:3
loop.index0:2
loop.revindex:2
loop.revindex0:1
/*** 4週目 ***/
最後
value:four
loop.index:4
loop.index0:3
loop.revindex:1
loop.revindex0:0

となります。これは重宝します。ちなみに、コンパイル後のphpは

<?php
    $v22032113141iterator = $numbers;
    $v22032113141incr = 0;
    $v22032113141loop = new stdClass();
    $v22032113141loop->length = count($v22032113141iterator);
    $v22032113141loop->index = 1;
    $v22032113141loop->index0 = 1;
    $v22032113141loop->revindex = $v22032113141loop->length;
    $v22032113141loop->revindex0 = $v22032113141loop->length - 1;
?><?php
    foreach ($v22032113141iterator as $index => $value) { 
?><?php 
        $v22032113141loop->first = ($v22032113141incr == 0);
        $v22032113141loop->index = $v22032113141incr + 1;
        $v22032113141loop->index0 = $v22032113141incr;
        $v22032113141loop->revindex = $v22032113141loop->length - $v22032113141incr;
        $v22032113141loop->revindex0 = $v22032113141loop->length - ($v22032113141incr + 1);
        $v22032113141loop->last = ($v22032113141incr == ($v22032113141loop->length - 1));
?>
	<?php if ($v22032113141loop->first) { ?>
    	    最初<br>
    	    loop.length:<?php echo $v22032113141loop->length; ?><br>
        <?php } ?>
        <?php if ($v22032113141loop->last) { ?>
    	    最後<br>
        <?php } ?>
        value:<?php echo $value; ?><br>
        loop.index:<?php echo $v22032113141loop->index; ?><br>
        loop.index0:<?php echo $v22032113141loop->index0; ?><br>
        loop.revindex:<?php echo $v22032113141loop->revindex; ?><br>
        loop.revindex0:<?php echo $v22032113141loop->revindex0; ?><br>
<?php 
        $v22032113141incr++;
    }
?>

コンパイル後のphpもごちゃごちゃしていますが、やってることは単純なのです。phpにて他の書き方もできますが、コーディング量は抑えられます。
※stdClassはhttp://php.net/manual/ja/language.oop5.basic.phpによると、定義済みのクラス。

演算子

以下の演算子はphpのものと使い方は同じです。

演算子

=
代入演算子
+=
加算代入
-=
減算代入
*=
乗算代入
/=
除算代入
+
加算
減算
*
乗算
/
除算
%
余り {{ 10 % 3 }} は、1が出力

比較演算子

==
型の相互変換をした後で両辺の値が等しければtrue
!=
型の相互変換をした後で両辺の値が等しくなければtrue
<>
型の相互変換をした後で両辺の値が等しくなければtrue
>
左の値が右の値より大きければtrue
<
右の値が左の値より大きければtrue
<=
左の値が右の値以上であればtrue
>=
右の値が左の値以上であればtrue
===
両辺の型と値が等しければtrue
!==
両辺の型と値が等しくなければtrue

論理演算子

A or B
AまたはBがtrueなら、trueを返す
and
AとBの両方がtrueなら、trueを返す

その他

以下のものは少し解説します。

~
演算子の両辺をつなげます。例えば、

{{ "hello " ~ "world" }}

の出力結果は「hello world」となり、phpで表現すると

<?php echo 'hello ' . 'world'; ?>

となる

|
前の演算子に対し、後ろの演算子にてフィルターをかける。例えば、

{{ "hello"|uppercase }}

の出力結果は「HELLO」となり、phpで表現すると

<?php echo Phalcon\Text::upper('hello'); ?>

となる

..
演算子の両辺の文字(1文字のみ)または整数の間のすべてを配列として返す。例えば、

{{ 'a'..'z' }}

は、phpで表現すると

<?php echo range('a', 'z'); ?>

となり、

{{ 1..10 }}

<?php echo var_dump(range(1, 10)); ?>

となる。出力結果は、array(10) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) [4]=> int(5) [5]=> int(6) [6]=> int(7) [7]=> int(8) [8]=> int(9) [9]=> int(10) }

is
==と同じ働きをする。例えば

{% if 'aaa' is 'bbb' %}

はphpで表現すると

<?php if ('aaa' == 'bbb') { ?>
in
演算子の左辺が右に含まれているかどうかチェックする。

{% if 'a' in 'abc' %}

これはtrueの処理になり、一方

{% if 'd' in 'abc' %}

は、falseの処理になる。phpで表現すると

<?php if ($this->isIncluded('a', 'abc')) { ?>

になる

is not
!=と同じ働きをする。例えば

{% if 'aaa' is not 'bbb' %}

はphpで表現すると

<?php if ('aaa' != 'bbb') { ?>
‘a’ ? ‘b’ : ‘c’
phpの三項演算子と同じ働きをする。

{{ true ? 'b' : 'c' }}

は「b」を出力、一方

{{ false ? 'b' : 'c' }}

は「c」を出力

++
phpと同様のインクリメント
phpと同様のデクリメント

長くなったので一旦ここまでです。
続きはVolt vol2に記載します。


投稿日: 2015年10月13日
カテゴリー: phalcon|php | 投稿者: