月別アーカイブ: 2011年10月

Zend Framework と Smarty

Smarty-2.26 を Zend Framework の View として使っていた (参考: Zend_View_Interface を使用したテンプレート) けれど、Smarty-3.1.3 にしたら、Smarty API の命名規則が変わったり、細部の挙動が異なっているなどして、そのままでは動かなくなってしまった。

修正のためいろいろ調べていたのだけれど、Zend のドキュメントの例って、あくまでも Zend_View_Interface の使い方の例として Smarty が持ち出されているだけで、Smarty の使い方の例というわけでもないのだ。

でも、Zend 公式に載ってるから、みんなそれをベースに修正して使ってるのだろう。

で、読んでるうちに、ベースの方向性の違いが気になってきて、いろいろと修正を試みていたのだが、
まあ、これでいいんじゃね? ってのができたのでメモしておく。

基本的な使い方は従来のものと同じ。大きな違いは、Zend_View_Interface の implement)でなく、Zend_View_Abstract の extends とし、Zend_View_Abstract で利用できそうな機構はなるべくそのまま利用するようにしているところ。

だから、従来比で Zend 多め、Smarty 少なめの依存度になっている。たとえば、Smarty::template_dir は設定せず、Zend 側のほうで用意してくれる script path (絶対パス) をテンプレートのパスとして使う、など。

ちなみに、Zend も Smarty もぜんぜん使い込んでないので、両者のいろいろな機能に対応していない箇所は多いとは思うが、そういうのはその都度修正して動くようにすればよいので。方向性としてはこんなもんかな、と思っている。

<?php
class Zend_View_Smarty extends Zend_View_Abstract
{
/**
* Smarty object
* @var Smarty
*/
protected $_smarty;
/**
* コンストラクタ
*
* @param string $tmplPath
* @param array $extraParams
* @return void
*/
public function __construct($config = array(), $extraParams = array())
{
require_once 'Smarty/Smarty.class.php';
$this->_smarty = new Smarty();
// Smarty::template_dir は設定しない
// Smarty::display() には Zend 側で生成したテンプレートの
// フルパスを渡すように $this->_script() で制御する
// Zend_View_Abstract::__construct() の実行
$config = (null === $config) ? array() : $config;
parent::__construct($config);
foreach ($extraParams as $key => $value) {
switch ($key) {
case 'plugins_dir':
$dirs = $this->_smarty->$key;
array_unshift($dirs, $value);
$this->_smarty->$key = $dirs;
break;
default:
$this->_smarty->$key = $value;
}
}
$this->_smarty->assignByRef('view', $this);
}
/**
* テンプレートエンジンオブジェクトを返します
*
* @return Smarty
*/
public function getEngine()
{
return $this->_smarty;
}
/**
* 変数をテンプレートに代入します
*
* @param string $key 変数名
* @param mixed $val 変数の値
* @return void
*/
public function __set($key, $val)
{
$this->_smarty->assign($key, $val);
}
/**
* empty() や isset() のテストが動作するようにします
*
* @param string $key
* @return boolean
*/
public function __isset($key)
{
return (null !== $this->_smarty->getTemplateVars($key));
}
/**
* オブジェクトのプロパティに対して unset() が動作するようにします
*
* @param string $key
* @return void
*/
public function __unset($key)
{
$this->_smarty->clearAssign($key);
}
/**
* 変数をテンプレートに代入します
*
* 指定したキーを指定した値に設定します。あるいは、
* キー => 値 形式の配列で一括設定します
*
* @see __set()
* @param string|array $spec 使用する代入方式 (キー、あるいは キー => 値 の配列)
* @param mixed $value (オプション) 名前を指定して代入する場合は、ここで値を指定します
* @return void
*/
public function assign($spec, $value = null)
{
if (is_array($spec)) {
$this->_smarty->assign($spec);
return;
}
$this->_smarty->assign($spec, $value);
}
/**
* Return list of all assigned variables
*
* Returns all public properties of the object. Reflection is not used
* here as testing reflection properties for visibility is buggy.
*
* @return array
*/
public function getVars()
{
return $this->_smarty->getTemplateVars();
}
/**
* 代入済みのすべての変数を削除します
*
* Zend_View に {@link assign()} やプロパティ
* ({@link __get()}/{@link __set()}) で代入された変数をすべて削除します
*
* @return void
*/
public function clearVars()
{
$this->_smarty->clearAllAssign();
}
/**
* Finds a view script from the available directories.
*
* @param string $name The base name of the script.
* @return void
*/
protected function _script($name)
{
// $name に対するフルパスを取得
$script_path = parent::_script($name);
// Smarty::compile_dir 内に置かれるコンパイル済みのテンプレートの
// 衝突回避のために Smarty::compile_id にディレクトリ名を設定する
$this->_smarty->compile_id = dirname($script_path);
return $script_path;
}
/**
* Includes the view script in a scope with only public $this variables.
*
* @param string The view script to execute.
*/
protected function _run()
{
// render() から呼び出される
// 出力は Zend 側でバッファされ、フィルタに渡されるので
// Smarty::fetch() ではなく Smarty::display() を使用する
return $this->_smarty->display(func_get_arg(0));
}
}
<?php
require_once "ZendViewSmarty.php";
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initView()
{
// application.ini から設定を読み出す準備
$options = new Zend_Config($this->getOptions());
// view.view.viewSuffix を取得
$viewSuffix = $options->view->viewSuffix;
// view.smarty.* の設定を配列で取得
$extraParams = $options->view->smarty->toArray();
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
$savedViewSuffix = $viewRenderer->getViewSuffix();
// 初期設定された Smarty オブジェクトを保持する
// Zend_View_Smarty オブジェクトのインスタンスを作成
// 1番目の引数は Zend_View_Abstract に渡す設定内容を表す
$view = new Zend_View_Smarty(null, $extraParams);
$viewRenderer->setView($view)
->setViewSuffix($viewSuffix);
}
}

application.ini の関連するところ

[production]
(略)
view.viewSuffix = "tpl"
view.smarty.compile_dir = APPLICATION_PATH "/../../smarty/templates_c"
view.smarty.plugins_dir = APPLICATION_PATH "/../../smarty/plugins"
(略)

ghostscript-7.07 のインストール

縦書きPostscriptファイルの表示のために、NetBSD に ghostscript-7.07 をインストールした。

なぜ、最新の Ghostscript にしないのか、というと、以前 8.x で試したときには、縦書きにしたときに全角の ‘-’ (ハイフン) が縦になってくれないなどの不具合、つまり縦書きにしたときに縦書き用のグリフになってくれない、という不具合があったからだ。

その時試したフォントは TrueType フォントだったが、 CID フォントだとどうなるのか、とか、別の TrueType フォントでも不具合が生じるのか、とか、OpenType だとどうなのか、とかいった検証はしていない。

とにかく、事実としてあるのは、手持ちの TrueTypeフォント (ヒラギノ行書体 TrueType 版) で、ghostscript-7.07 では縦書き Postscript を期待通りに表示してPDFに変換できたのに対し、8.x は期待に答えてくれなかった、ということだ。

とはいえ、ghostscript-7.07 は pkgsrc からなくなってしまっているので、自分で build する必要がある。配布ファイルもいつまで提供されるのかはわからないが、現時点での覚書を作成しておくことにする。

参考にしたサイト

必要なファイル (2011.10.11現在の情報)

  • ghostscript-7.07.tar.bz2
    sourceforgeからもってこれる。まだ入手可能。
  • ghostscript-fonts-std-8.11.tar.gz
    ghostscript-fonts-other-6.0.tar.gz
    どちらもsourceforgeにある。
    ghostscript-fonts-std-8.11.tar.gz は ghostscript-fonts-std-6.0.tar.gz の方を使うほうが正しいかもしれない。どちらでも普通に動作するように見える。
  • jpegsrc.v6b.tar.gz
    CTAN:support/ghostscript/3rdparty/jpegsrc.v6b.tar.gz から入手可能。
    本家であるIndependent JPEG Group のサイトからは入手できない(v8b になっている)。v7 のときにはそのままでは使えなかったので、多分 v8 でもダメだろう。
  • adobe-cmaps
    pkgsrc/fonst/adobe-cmaps (adobe-cmaps-20060615)が利用できる。
    NetBSD であれば pkgsrc で adobe-cmaps をインストールして、できたファイル群 (/usr/pkg/share/Adobe/Resource/CMap にシンボリックリンクが作成される) をコピーするのが楽だと思う。
    元ファイルが O’Reilly
    から入手できるかと思ったが、既に違うファイル(後継のファイル?)に置き換わっている。また、http://partners.adobe.com/public/developer/en/pdf/ (リンク切れ) から数点のファイルを持ってくる必要があるようだが、オリジナルの所在は不明。

    Adobe から持ってくる場合、
    CMap Resources
    に加えて
    Mapping Resources for PDF
    を持ってくればいいみたい。入れてみたら動いた、というだけなので細部まで含めてちゃんと動いているのかどうかはわからない。

インストールの手順

以下は、デフォルトの /usr/local 以下にインストールする前提で記述している。

展開する。

$ tar xzf ghostscript-7.07.tar.bz2
$ tar xzf jpegsrc.v6b.tar.gz

jpeg-6b のソースツリーを jpeg という名称で ghostscript のソースツリーの下に移動する。

$ mv jpeg-6b ghostscript-7.07/jpeg

lib/gs_res.ps の 249-250行目、/FontResourceDir、/GenericResourceDir の設定 (/Resource/Font/、/Resource/) を、/usr/local/share/ghostscript/Resource/Font/、/usr/local/share/ghostscript/Resource/ に変更する。

--- lib/gs_res.ps
+++ lib/gs_res.ps
@@ -246,8 +246,8 @@
/pssystemparams 10 dict readonly def
} if
pssystemparams begin
-  /FontResourceDir (/Resource/Font/) readonly .forcedef        % pssys'params is r-o
-  /GenericResourceDir (/Resource/) readonly .forcedef  % pssys'params is r-o
+  /FontResourceDir (/usr/local/share/ghostscript/Resource/Font/) readonly .forcedef    % pssys'params is r-o
+  /GenericResourceDir (/usr/local/share/ghostscript/Resource/) readonly .forcedef      % pssys'params is r-o
/GenericResourcePathSep (/) readonly .forcedef       % pssys'params is r-o
end
end

Makefile.in の XLDFLAGS を修正する。

- XLDFLAGS=
+ XLDFLAGS=-Wl,-rpath,/usr/pkg/lib

configure を実行する。

(X Window System なしの場合)
$ cd ghostscript-7.07
$ ./configure
(X Window System ありの場合)
$ cd ghostscript-7.07
$ ./configure --with-x --x-includes=/usr/pkg/include --x-libraries=/usr/pkg/lib

コンパイル(BSD make だとうまく動かない)

$ gmake

インストール

$ sudo gmake install
$ cd /usr/local/share/ghostscript
$ tar xzf ghostscript-fonts-std-8.11.tar.gz

Adobe のサイト から以下のファイルをダウンロードする。

$ sudo mkdir /usr/local/share/ghostscript/Resource
$ cd /usr/local/share/ghostscript/Resource
$ sudo tar xzf cmapresources_identity0.tar.z
# (以下、同様に全ファイルを /usr/local/share/ghostscript/Resource 下に展開)
$ sudo mkdir CMap
$ cd CMap
$ for i in ../*/CMap/*; sudo ln -s $i .; done
$ for i in ../ToUnicode/* ../MappingOther/*; do sudo ln -s $i .; done

後は、/usr/local/share/ghostscript/7.07 の CIDFnmap にフォントを定義するか、フォントを定義した CIDFnmap をカレントディレクトリに置いておけば良い。

例えば、以下の内容の CIDFnmap と フォントファイル dshirgy4.ttc をカレントディレクトリに置いておくと、HiraginoGyoDS-W4 としてヒラギノ行書体フォント(TrueType版)が利用できる。

/HiraginoGyoDS-W4       (./dshirgy4.ttc) ;

PC不調

Windows7 を入れているPCが不調になった。電源ON後、BIOS画面の途中(HDDを識別しているあたり)で、動かなくなったり、稼働中に動かなくなったり突然再起動がかかったり。

その内に、どこかのファイルが壊れたか、Windows Aero が効かなくなった。半透明のはずのタスクバーが不透明のグレーになっている。

起動ディスクを使って修復を試みたが、治らない。

やむを得ず、数日前のバックアップを書き戻してやると、治った模様。

と思ったら、しばらくして、再度同じような展開(不安定→Aero停止)で障害が発生した。

電源が怪しいかも、と思って、Amazon でATX電源(サイズ ショートタイプATX電源 剛力短2プラグイン 500W 80PLUSブロンズ SPGT2-500P)を購入(6,421円)、入替。バックアップを書き戻して様子を見る。

しかし改善しない。障害発生のパターンは同様。

外したかな? と思ったが、交換した電源はずいぶんと古いものだったので、交換時期に達していたとして、必要な出費と自らに言い聞かせる。

次に怪しいのはHDD周り。でも、HDD、マザーボード、ケーブルの3パターンは考えられる。

ここは思い切って、総替えで行くことにした。ツクモでまとめ買い(計56,521円)

CPU Intel Core i7 2600 Box (LGA1155) 23,940円
マザーボード GIGABYTE GA-Z68XP-UD3 2,980円
メモリ Patriot DDR3-1333 4GB×2枚 PSD38G1333K 3,680円
ビデオカード GIGABYTE GV-R645OC-1GI (Radeon HD6450) 4,681円
HDD HITACHI Deskstar 2TB 0S03224 6,780円
DVD multi LG GH24NS70SL 2,480円
HDDケース MARSHAL MAL-1335B/S 1,980円
合計 56,521円

ビデオカードとか直接関係ないけど、今まで使っていたのが古い(nVidia 7600GS)ので、この機会に入れ替えることにした。DVD multi-drive は、今までのがIDEで、今度のマザーボードにIDEはついてないので必然的に入替えることに。メモリはDDR2の頃と比べても劇的に安くなっているなあ。

最初にHDD以外の全てを入れ替えても、症状変わらず。じゃあ、HDDが原因か、ということでHDDを入れ替えて、バックアップを新しいHDDに書き戻すと、2、3日大丈夫だと思ったら、やっぱりその後ダメに。

結局、まるごと新しいシステムに、Windows7を再インストールすることで落ち着いた。バックアップイメージが既に壊れたシステムのバックアップとなっていたようだ。

調子の悪かったHDDは S.M.A.R.T ツールで確認すると幾つかのパラメータが警告状態となっていた。昨年9月の購入だから使用期間は丸1年立つか立たないかくらい。ネットで調べると Wentern Digital の WD20EARS-R は Advanced Format 絡みの性能低下の話を抜きにしてもずいぶんと評判が悪いみたいだ。

当分、Western Digital は購入禁止だな。でも、日立はWDになっちゃうのか。