エラーを例外に変換。

エラーを例外に変換するのは、一般的な手法らしい。

http://www.phppro.jp/news/185

function handleError ($errno, $errstr, $errfile, $errline) {
  if ($errno & error_reporting()) {
    throw new RuntimeException($errstr, $errno);
  }
}
set_error_handler('handleError');

サンプルではerror_reportingに対応していない様なので、修正してみた。

Smartyテンプレート上では、E_NOTICEが頻繁に発生する。(アサインしていない変数をif式から参照したり)
Smarty自身は、error_reportingを適宜書き換えることによってこの問題に対応している(Smarty::fetch())が、その仕組みをそのまま生かす為には、エラーハンドラの側でもerror_reportingに対応する必要がある。


以上、備忘録。

favicon wars

外部サイトのフィードを、BOTにクロールさせる。
それ自体はよくある処理だが、ついでにfaviconも取得し、適切な画像(例えばPNG)に変換してキャッシュする。


ico形式をPNGに変換するところが、この処理のキモだ。
GD2はico形式に対応しておらず、何かしら対策が必要。
ImageMagickならば対応している様だが、残念ながら、それを利用できる環境ではない。


PHP用のico対応ライブラリは、程なく見つけることが出来た。


class.ico.php
http://www.phpclasses.org/browse/file/9705.html


ソースを見たところ、内部処理をGDで行っている。
これなら問題なく動くだろう。


まずは試しにこのブログ、つまりはてなダイアリーfaviconを拝借。

ふむふむ、ちゃんとゲットできてる。
こりゃいい。


では続けて、twitter

え。なにこれ。
なにこの、不思議時空。


言うまでもないけど、以下のカラーリングが正解。


この変色は、class.ico.phpのバグが原因とのことで。
修正の手順は、こちら。


PHP ICO to PNG conversion | Tom Reitz
http://www.tom-reitz.com/2009/02/17/php-ico-to-png-conversion/


情報提供に感謝です。
とても助かりました。

Smartyのテンプレート関数 assign

Smartyのテンプレート関数 assign について、配列をアサインできない仕様を、ずっと以前から不便に感じていた。


通常、assign関数はこんな風に使うけど、

{assign var='a' value='hoge'}
{assign var='b' value='fuga'}
<html><body>
<p>{$a}</p>
<p>{$b}</p>
</body></html>


それをこんな風にも使えれば、便利ではないかと。

{assign var='array.a' value='hoge'}
{assign var='array.b' value='fuga'}
{assign var='array.c.1' value='foo'}
<html><body>
<p>{$array.a}</p>
<p>{$array.b}</p>
<p>{$array.c.1}</p>
</body></html>


該当するコードは plugins/compiler.assign.php とわかった。
このファイルではファイル名通り、 smarty_compiler_assign 関数を実装している。

この関数をこんな風に書き換えてみたら、希望通りの動作を実現できた。

<?php
function smarty_compiler_assign ($params, &$compiler) {
  $params = $compiler->_parse_attrs($params);

  if (!isset($params['var'])) {
    $compiler->_syntax_error('assign: varが未定義です。', E_USER_WARNING);
    return;
  }
  if (!isset($params['value'])) {
    $compiler->_syntax_error('assign: valueが未定義です。', E_USER_WARNING);
    return;
  }

  $var = null;
  foreach (explode('.', str_replace('.', "'.'", $params['var'])) as $part) {
    if ($part == "''") {
      $var .= '[]';
    } else {
      $var .= '[' . $part . ']';
    }
  }

  return '$this->_tpl_vars' . $var . '=' . $params['value'] . ';';
}


本来テンプレートに書くべき...と思われる内容を、仕方なくphp側に書いたりしてたけど、一掃できてうれしい。
それにしても、このアイデアをもっと早く気づけなかったものか。

Leopardのリゾルバキャッシュをクリア

ネームサーバのメンテを行うとき等、意外と頻繁に必要になるが、つい忘れてしまう。

dscacheutil -flushcache


これをAppleScriptにして、デスクトップに置いておけば完璧だ!

do shell script "dscacheutil -flushcache"


...さぁ仕事、仕事。

ちょっとE! エンタメをチョイス!! ChoE!

今日は珍しく、会社としてのお知らせ。
4月末から着手していた案件が、本日遂に公開となりました。


ちょっとE! エンタメをチョイス!! ChoE!
http://www.choe.jp/


エンタメ系のポータルサイト、とでも言えば良いでしょうか。
お盆休みの行楽のお供に、是非ご活用ください。


少しだけテクニカルな説明を。
このサイトの大半のページは、専用のCMSで制作されたコンテンツです。1回の登録から、PC向けとケータイ向け(勝手サイト)のページを生成します。その為に必要であれば、画像の各種変換を行います。
あと、ドロップダウンメニューも使ってます。(というか、このサイトの為に開発したものなので)


実は、今回実装しなかった仕掛けがたくさんあります。
こういった数々の仕掛けも、少しずつお見せできると思います。

皆さんにお楽しみいただければ、開発者としても嬉しいです。
ご訪問をお待ちしております。

ドロップダウンメニュー usermenu.js

とあるサイトの画面上部にドロップダウンメニューを設置する依頼を受け、 "LEIGEBER web development blog" で配布している "dropdown.js" を改造した。
思いのほか汎用性が高いものに仕上がったので、こっそり配布させて頂く。 :-)

usermenu.js ダウンロード
サンプル


全コード書き直したけど、ロジック自体はこちらで配布しているものとほぼ同じ。

LEIGEBER web development blog
Sliding JavaScript Dropdown Menu


依頼ではメニューがタブ状の画像であり、また、マウスオーバー時にタブ画像をハイライトさせる必要があった。
dropdown.jsをそのまま利用するのでは実現できず、この点を含めた以下の機能追加を行った。

  • テキストではなく、画像のメニュー。
  • マウスオーバー時、メニュー画像を差し替え。
  • 透明度等、各種パラメータの調整。
  • HTMLマークアップの簡略化。

これらを実現している代わりに、 prototype.js に依存してしまっている点にはご容赦頂きたい。
設置手順は以下の通り。


まず、prototype.js, usermenu.js, usermenu.css を読み込む。
設置先ページのhead要素内に、以下の記述を追加。

<script type="text/javascript" src="/path/to/prototype.js" charset="utf-8"></script>
<script type="text/javascript" src="/path/to/usermenu.js" charset="utf-8"></script>
<link rel="stylesheet" type="text/css" href="/path/to/usermenu.css" />


次に、メニューのマークアップを行う。
以下、サンプル。

<div id="usermenu">
  <dl id="usermenu_sample1">
    <dt><a href="#"><img src="images/spacer.gif" width="60" height="25" alt="HOME" /></a></dt>
  </dl>
  <dl id="usermenu_sample2">
    <dt><img src="images/spacer.gif" width="60" height="25" alt="DIARY" /></dt>
    <dd>
      <ul>
        <li><a href="0701.html">7/1</a></li>
        <li><a href="0702.html">7/2</a></li>
        <li><a href="0703.html">7/3</a></li>
        <li><a href="0704.html">7/4</a></li>
      </ul>
    </dd>
  </dl>
</div>
<script type="text/javascript">
  new UserMenu('sample1');
  new UserMenu('sample2');
</script>

マークアップは、以下のルールに従い行う。

  • ドロップダウンメニュー全体を、ブロック(id "usermenu" )でくくる。
  • 各々のメニューを、dl要素でくくる。idは、 "usermenu_" に続けて任意のメニュー名。(このメニュー名は、JavaScript記述でも使用する、後述)
  • メニューの中にdt要素を置き、適当な画像(img要素)を置く。画像の中身はよくあるスペーサーGIFで良いが、width, height, alt属性は、正しい値をきちんと記入しておく。また、画像自体をaタグでくくってリンクにしてもよい。
  • メニューがメニュー項目を持つ場合は、メニューの中にdd要素を置き、その中に更にulリスト(ul,li要素)を置いてメニュー項目を記述する。メニュー項目をひとつも持たないメニューには、dd要素を記述しない。


マークアップが出来たら、usermenuブロックの外にscript要素を置く。
dl要素のところで定義したメニュー名を引数として(dl要素のidが "usermenu_sample1" ならば、メニュー名は "sample1")、定義したdlひとつごとに対応するUserMenuオブジェクトを生成する。


次に、素材画像の設置を行う。
設置先ページからの相対参照で images/usermenu に相当するディレクトリに、 <メニュー名>.gif と <メニュー名>_on.gif を置く。(メニュー名が "sample1" ならば、 sample1.gif と sample1_on.gif)
前者は通常時の画像、後者はマウスオーバー時の画像。両画像のピクセルサイズは一致させること。


最後に、usermenu.cssの調整。
設置先ページをリロードしながら、ページレイアウトに合わせた各種調整をusermenu.cssに対して行い、設置完了。


サンプルで利用しているうさぎ素材は、うさぎ小屋さんからお借りしました。
いつもお世話になってます。また美味いもの食いに行きましょう。>うさ番

動作保証はしませんが、ご利用・各種流用等はご自由に。


2009/08/22追記:
一部のIE環境で起きる不具合を修正。