2008年1月17日木曜日

【modifier】テンプレート上のSmarty変数をPHP関数で扱う

ITpro
【PHP TIPS】 68. Smartyのmodifierを使いこなそう

Smartyでは 、assignされた変数に処理を与えるmodifier という機能がある。
PHP関数をパイプ「|」でつなげて記述して使用します。

$smarty->assign('name', 'atsushi');

上記のコードをPHPファイル内に記述して変数をアサインする。 テンプレート内で文字を大文字にするstrtoupper()関数で処理するにはに

{$name|strtoupper}
//結果:ATSUSHI

modifierに配列を渡す場合は、関数名の前に「@」をつける。

$name_list = array(
    '0' => 'atsushi',
    '1' => 'yoshiki',
    '2' => 'miwa',
    '3' => 'hiroshi',
    '4' => 'saito'
);
$smarty->assign('name_list', $name_list);
{$name_list|@count}
//結果:5

modifierには「:」をつけることで引数を渡すこともできる。

{$name|substr:'1':'3'}
 //結果:tsu

modifierでは、パイプの前の変数とコロンの後に指定した値が、並べた順番にそのまま関数に渡される。
例えば、{$name|str_replace:'shi':'ko'}だとstr_replace($name, 'shi', 'ko')渡していることになる。
str_replace('shi', 'ko', $name); のように渡したい場合は次のようになる。

{'shi'|str_replace:'ko':$name}
//結果:atsuko
{'/a|i|s/'|preg_replace:'!':$name}
//結果:!t!u!h! 
参考
ITpro 総合トップ
http://itpro.nikkeibp.co.jp/index.html

2007年12月28日金曜日

php+smartyで動いているPC用のサイトをテンプレートだけ変えて携帯サイトに変換する方法をご紹介。

php+smartyで手抜きケータイサイトをつくる。

1.ユーザーエージェントやIPなどで携帯からのアクセスか、パソコンからのアクセスかを判別する。
2.携帯からのアクセスだった場合はsmartyのテンプレート関連ディレクトリを携帯用のテンプレートを入れたディレクトリに切り替え。
>※携帯用のテンプレートはPC版と同じ文字コードにしておいてください。
3.$smarty->displayしてるとこでPCからのアクセスだった場合はそのままdisplayで表示させる。
携帯からのアクセスだった場合は$smarty->fetchで表示結果を変数に取得し、mb_convert_encodingを使って文字コードをSJISに変換して変数の内容をecho()で書き出し。

みるくぜりー| php+smartyで手抜きケータイサイトをつくる。

詳しいところはリンク先を参照。
PEARを使った携帯・PCのアクセス判別や、テンプレート・ディレクトリの切り替えに関するソースを省いた必要な部分が以下。
それらがあったほうが便利で楽だが、PEAR使えないサーバもあるので。


class Smarty_Ex extends Smarty{
    function display($template, $cache_id = null, $compile_id = null)
    {
          //携帯なので結果をいったん変数に
          $output=parent::fetch($template);
          //半角カナにしてパケ代をとりあえず節約。
          $output=mb_convert_kana($output,"k","UTF-8");
          //SJISに変換しましょう。
          $output=mb_convert_encoding($output,"SJIS","UTF-8");
          echo $output;
    }
}

上のクラスはsmartyオブジェクトを継承してるので、使うときは変わらず。以下の通り。
上のクラスでは、キャリアの判別とディレクトリ切り替えをしてないので、実際使うときはPCと携帯のそれぞれで別のテンプレート・ファイルを呼び出すようにする必要がある。


$smarty=new Smarty_Ex();//smartyオブジェクト作成
$smarty->assign('var',$var);
$smarty->display("index.tpl");

2007年11月8日木曜日

【assign】テンプレートでの変数の定義

テンプレートファイル内で変数を定義するには{assign}関数をつかう。


{assign var="var" value="`$val1 + $val2`"}

使うときは他の変数と同様に{$var} var変数名value
"`"で囲むと文字列ではなく計算式として扱う

【foreach】テンプレート内での繰り返し・ループ

配列のSmarty変数をループさせるにはforeachがある。

{foreach from=$data item="value" key="key"  name="loop"}
  {if $smarty.foreach.loop.first}
     最初:{$key}:{$value}
  {elseif $smarty.foreach.loop.last}
     最後:{$key}:{$value}
  {else}
    {$smarty.foreach.loop.iteration}:{$key}:{$value}
  {/if}
{foreachelse}
   データがありません
{/foreach}

itemfromの指定は必須。
配列のキーを使うにはkeyの指定が必要。 以下のSmarty予約変数を使うにはnameの指定が必要。

$smarty.foreach.loop.first … 最初の要素かどうか
$smarty.foreach.loop.last … 最後の要素かどうか
$smarty.foreach.loop.iteration … 現在のインデクス(何回目のループかカウント)

2007年10月9日火曜日

foreachとsectionの比較

Smartyforeachsectionではどちらを使った方が良いか

プログラミングにおいて、同じような処理をする関数ではどちらが処理速度が速いのか、というのは議論になるところと思います。
PHPではecho()print()だったり、ループではdo()while()for()だったり。
当たり前ですが、処理が単純で引数などがない方が速い様に思います。確か条件分岐があるだけでもプログラムの処理は一気に遅くなるというのをC言語で計測した覚えが有ります。

Smartyでのループ処理のforeachsectionでは、属性が多く細かな設定が可能なsectionよりforeachの方が好ましいようです。

がるの健忘録 - 2006-09-22

リンク先では、Smartyテンプレートエンジンがテンプレートファイルを解析して作られるキャッシュファイルを比較してます。実際に表示されるのはキャッシュのPHPファイルでしょうから、ソースが増えれば遅くなるでしょう。

{foreach from=$custid item=curr_id}
        id: {$curr_id}
{/foreach}

<?php $_from = $this->_tpl_vars['custid']; if (!is_array($_from) && !is_object($_from)) { settype($_from, 'array'); }if (count($_from)):
    foreach ($_from as $this->_tpl_vars['curr_id']):
?>
        id: <?php echo $this->_tpl_vars['curr_id']; ?>
<br>
<?php endforeach; endif; unset($_from); ?>

に。このあたりから微妙なニュアンスが漂います。
おっかないのがsection。どっちもループだよねぇ、程度に思ってたのですが………甘いも甘いも大甘。
{section name=customer loop=$custid}
        id: {$custid[customer]}<br>
{/section}
が、なんと…
<?php unset($this->_sections['customer']);
$this->_sections['customer']['name'] = 'customer';
$this->_sections['customer']['loop'] = is_array($_loop=$this->_tpl_vars['custid']) ? count($_loop) : max(0, (int)$_loop); unset($_loop);
$this->_sections['customer']['show'] = true;
$this->_sections['customer']['max'] = $this->_sections['customer']['loop'];
$this->_sections['customer']['step'] = 1;
$this->_sections['customer']['start'] = $this->_sections['customer']['step'] > 0 ? 0 : $this->_sections['customer']['loop']-1;
if ($this->_sections['customer']['show']) {
    $this->_sections['customer']['total'] = $this->_sections['customer']['loop'];
    if ($this->_sections['customer']['total'] == 0)
        $this->_sections['customer']['show'] = false;
} else
    $this->_sections['customer']['total'] = 0;
if ($this->_sections['customer']['show']):

            for ($this->_sections['customer']['index'] = $this->_sections['customer']['start'], $this->_sections['customer']['iteration'] = 1;
                 $this->_sections['customer']['iteration'] <= $this->_sections['customer']['total'];
                 $this->_sections['customer']['index'] += $this->_sections['customer']['step'], $this->_sections['customer']['iteration']++):
$this->_sections['customer']['rownum'] = $this->_sections['customer']['iteration'];
$this->_sections['customer']['index_prev'] = $this->_sections['customer']['index'] - $this->_sections['customer']['step'];
$this->_sections['customer']['index_next'] = $this->_sections['customer']['index'] + $this->_sections['customer']['step'];
$this->_sections['customer']['first']      = ($this->_sections['customer']['iteration'] == 1);
$this->_sections['customer']['last']       = ($this->_sections['customer']['iteration'] == $this->_sections['customer']['total']);
?>
        id: <?php echo $this->_tpl_vars['custid'][$this->_sections['customer']['index'; ?>
<br>
<?php endfor; endif; ?>

がるの健忘録

細かい設定などが必要ないときはforeachを使った方が良さそうです。

参考

がるの健忘録
http://d.hatena.ne.jp/gallu/

2007年8月3日金曜日

時刻のselect要素が作成できる - {html_select_time}関数


{html_select_time prefix="" field_array="time" time=$smarty.now  display_seconds=false minute_interval="30"}

実行例:  

prefixは各要素名の接頭辞。デフォルトがTime_なので(各セレクト名はTime_HourTime_MinuteTime_Second)付けない様にNULL
field_arrayを指定する事で、時間要素が連想配列で$_POSTに渡される(例だと$_POST["time"]=Array(["Hour"],["Minute"],["Second"]))。
"秒"と"分"の選択メニューは1~30(秒/分)刻み
true/falseは"(クウォート)で括ったり大文字で記述する(TRUE/FALSE)とうまくいかない様です。

属性(<html_select_date>との共通)

prefix
name属性に負荷する接頭辞[デフォルト:Date_、Tme_]
time
デフォルトセットの日付(YYYY-MM-DD形式かUNIXタイムスタンプで指定)[デフォルト:現在の日付・時刻]
field_array
入力値を連想配列としてPHPに渡す
all_extra
全ての<select>タグの属性指定

属性(<html_select_time>の固有)

display_hours
時のプルダウン表示[true/false](デフォルト:true)
display_minutes
分のプルダウン表示[true/false](デフォルト:true)
display_seconds
秒のプルダウン表示[true/false](デフォルト:true)
display_meridian
AM/PMの表示[true/false](デフォルト:true)
use_24_hours
24時間表示[true/false](デフォルト:true)
minute_interval
分のプルダウンメニューの間隔[1~30](デフォルト:1分)
second_interval
秒のプルダウンメニューの間隔[1~30](デフォルト:1秒)
hour_extra
時の<select>タグの属性
minute_extra
分の<select>タグの属性
second_extra
秒の<select>タグの属性
meridian_extra
AM/PMの<select>タグの属性