テンプレート内での文字列の連結

2008/04/22 | Smarty

Smartyテンプレート内で、変数に格納された文字列の結合をしたい場合がある(つまり「変数を結合したい」のだが)。

単に文字列を結合するだけならcat修飾子でいい。
{$str1|cat:’_add’}とか{$str1|cat:$str2}とか

結合した文字列を他の処理で使いまわしたいということはないだろうか。たとえば上記の処理で得られる文字列をキーとした配列中の値を取得したいとか・・・。
そんなときにはassign関数が使えるのだが、たいていの場合は期待通りの動作をしてくれない。しかし記述方法ひとつで、しっかりと動作してくれる。それは「バッククォート(`)」だ。

例えば変数$str1と$str2を結合した$strを作りたいときはこんな具合に記述する。

{assign var=str value=”`$str1“$str2`”}

仮に$str1=’abc’、$str2=’def’だとしたら、$strは’abcdef’になる。
こういうの、マニュアルに書いてあればいいのに。

テンプレート内での分割処理

2008/04/21 | Smarty

テンプレートエンジンSmartyで、割り当てられた変数(配列)を分割するための関数を作ったのでメモ。

例えばリンク集(バナーで表示)を作るって表形式で表示したい場合、表の列数によってテンプレート内で「行の開始かどうか(<tr>タグを出力するかどうか)」「行の終了かどうか(</tr>タグを出力するかどうか)」といったロジックを書くことになる。テンプレート内でのロジックは減らしたいので、上記のように書くのはあまり好きではない。

PHPには便利な関数array_chunkというのがある。配列を指定した個数の配列に分割してくれるというものだ。さらに便利な関数でarray_padというのがある。指定個数に満たない配列を、指定した値で満たしてくれる関数だ。

一番簡単なのはコントローラ(もしくはメイン処理)で、上記の処理を入れることだが、表示を変更したい(例えば表の列数を増減したい)場合は、コントローラのプログラムを変更しなければならず、本来表示側だけで対応したいのに、本末転倒となるわけだ。

んで、Smartyの関数を作って、テンプレート内で分割できるようにした。関数はfunction.array_split.phpという名前で、以下の内容で、しかるべき場所に保存。

<?php
  function smarty_function_array_split($params, &$smarty)
  {
    $paramKey  =$params[‘var’];
    $paramValue  =$params[‘value’];
    if(is_null($paramValue)){
      $paramValue=array();
    }
    $paramSplit  =$params[‘split’];
    
    if($paramValue){
      $paramSplitted=array_chunk($paramValue,$paramSplit,true);
      $lastValue=array_pop($paramSplitted);
      $lastValue=array_pad($lastValue,$paramSplit,NULL);
      array_push($paramSplitted,$lastValue);
    }else{
      $paramSplitted=array();
    }
    $smarty->assign($paramKey,$paramSplitted);
  }

もうちょっとエラー処理を入れなくてはいけないけれど・・・。
もっと早くに関数作ればよかったな。

SECOMのSSLはかなりイタダケナイ

2008/04/20 | その他

PHPとは関係ないお話。
先日ウェブサーバにSSL証明書をインストールしたのだが、えらく時間がかかってしまったのでメモ。

今までは、基本的に自社でSSLを使用する際はThawte社を使っていた。いちおうベリサインの子会社だし、証明書の発行数はベリサインについで2位だし、何より安いし、販売代理店にもなったし・・・。難点なのは「南アフリカ」の会社、というところなのだが、現地に日本人スタッフがいてメールは日本語でのやり取りもできるので問題はない(Thawteの証明書がほしい人は連絡くれれば手伝う・・・かもしれない)。
今回とある仕事で、携帯からの使用を想定し、携帯でもOKなSSL証明書を使うことになった。日本で携帯SSLといえばベリサインかセコムか、といったところ(ボルチモアも大丈夫だったっけか)。んで、セコムを使うことになった。実はこれがそもそもの間違いで、証明書の費用はクライアントが負担するのだから、「ベリサインにしておけばよかった」と後悔している。

今回使用したのは「セコムパスポート for Web」。で、導入手順はこんな感じ。

(1) キー作成、CSR作成(これはどこでも同じ)
(2) 申請(セコムは証明書発行後の請求書払い、とこの点は評価できる)
(3) 電話連絡後、証明書発行
(4) インストール

このインストールでつまずいた。というのもセコムの証明書をインストールするときは「中間CA証明書」をインストールしないといけないのだ(ベリサインやThawteでは不要だった)。そして、そのインストール作業にもしっかりとお約束事があった。
で、作業はこんな感じだった(失敗も含めて書いてみる)。

(1) 証明書をダウンロードして、証明書をインストール(apache設定)
(2) apache再起動
(3) 「この証明書は信頼できる機関から発行されていません」(ふざけるな!)
(4) 原因を調べると中間CA証明書のインストールが必要(トップページに書いておいてくれ!)
(5) 中間CA証明書を取得してインストール(apache設定)
(6) 「この証明書は信頼・・・」(なめてんのか)
(7) apacheのコメントアウト欄にない設定項目が必要だった(設定するところを間違えていた)
(8) 再設定してapache再起動(SSLCACertificatePath)
(9) 「この証明書は信頼・・・」(し・・・しばく・・・)
(10) 設定したディレクトリにおくファイル名が決まっていた(赤太字でかけ!)
(11) 中間CA証明書のファイル名をfe686ec0.0に変更して再設定
(12) apache再起動
(13) やっと動いたよ(数万円が無駄にならずに済んだ・・・)

所詮「セコム」。そういえばベリサインの電話確認と比べればいい加減だった。ベリサインなら、作成する証明書のホスト名を、必ずアルファベットを順番に読んで確認したけど、セコムの場合は「○○.jp」ですね、だったし(微妙にスペルが違ってたらどうするつもりなんだろ)。

お約束事は赤太文字で書いてよ。
ま、動いてよかったよ。

try、throw、catch・・・その2

2008/04/19 | PHPの基本

try{}catch(){}構文の研究中につき、理解できた範囲をメモ。
PHP5から使えるようになったJAVAライクなエラー処理だが、慣れない自分にとっては理解に苦しむ記述なので、自分でいろいろ試してみることにした。
こんなスクリプトを書いた。

class myException extends Exception
{
}

class myClass
{
  function __construct()
  {
    print(‘1′);
    print(‘2′);
    throw(new myException(‘error’));
    print(‘3′);
    print(‘4′);
  }
}

try{
  $obj=new myClass;
}catch(myException $e){
  exit();
}

まずExceptionというクラスを継承してmyExceptionという派生クラスを作った。別に特別な処理をしているわけではないけれど、いろいろ調べたかったので、まずは派生クラスを定義しておいた。
次に実際に例外を投げるクラスをつくった。このクラスのコンストラクタの中で、
throw(new myException(‘error’));
と単に例外を投げるように記述した(実際はif文とか使ってエラーが発生した場合に例外を投げることは言うまでもない)。
最後のところで実際にオブジェクトを生成する処理を書いてある。
これを自分なりに読んでいく。

throw(new myException(‘error’));
throw関数の引数は例外として生成したオブジェクトらしい。おそらくいろいろな例外をあらかじめ想定し、例外の種類に応じてそれぞれの例外派生クラスを引き当てるのだろう。この例外クラスの引数は文字列でないといけないっぽい。つまりエラーメッセージをセットするようなイメージだろうか。いちおうもうひとつ引数を取れるみたいで、そちらにはエラーコード(番号)をセットするような感じ。

エラーが発生(例外をthrow)すると、そのスクリプトは途中で中断され(上記で言えば関数内の処理が途中で中断され)、catch構文へ処理が遷移することになる。

catch(myException $e)
この構文の意味がなかなか理解できなかった。どうやらmyExceptionのところは事前に想定した例外のクラス名を割り当てる(のだと思う)。後ろの$eはというと、実はここは$abcでも$errorでも何でもよさそう。new myException(‘error’)で「作りっぱなし」かよ、と思えたオブジェクトはこの変数に代入されるようだ。
あとは$eを煮るなり焼くなりすればいい。

ちなみに、いくつもの例外を想定するわけだから、実際はこんな記述になるのだろうか。

try{
  $obj=new myClass;
}catch(my1Exception $e){
  exit();
}catch(my2Exception $e){
  exit();
}catch(my3Exception $e){
  exit();
}catch(Exception $e){
  exit();
}

いろんなエラーを想定しておいて、どれに合致するか試してみて、それにも合致しないエラーが出てしまったら最後のデフォルトの例外クラスでキャッチ。

理解できたようなできていないような・・・。まだしっくりこない。

classに関するメモ

2008/04/18 | PHPの基本

PHPのクラスに関するメモ。
クラスAとそれを継承したクラスBのコンストラクタに関して、時々どうだったっけ、と思うのでメモしておく。

class A
{
  function A(){print(‘A’);}
}

クラスBにコンストラクタがない場合
class B extends A
{
}
$obj=new B;
// Aと表示される(親クラスのコンストラクタが実行される)

クラスBにコンストラクタがある場合
class B extends A
{
  function B(){print(‘B’);}
}
$obj=new B;
// Bと表示される(親クラスのコンストラクタは実行されない)

コンストラクタはPHP5以降、__construct()とも書けたりもするのでこんがらがってしまうけど、__construct()のほうがわかりやすい。

だって、
class B extends A
{
}

って書いてるのだから、コンストラクタはB()か__construct()であって、A()がコンストラクタにはならないほうがいいように思う。だって複数回継承されたときの元のコンストラクタがなんだったかわからなくなるから。昔からの名残だからしょうがないんだろうけど・・・。
やはりPHP5ライクな記述を目指すべきだと思った(PHP4の環境が当面なくなりそうにないからしょうがないか)。


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net