symfonyの最近のブログ記事
symfonyでモバイルの開発をする際に、とても参考になるテクニック満載のスライドです。
この中でdocomo、au、SoftBankのキャリア別にinputタグの入力モードを切り替えるカスタムヘルパーが紹介されていますが、省略されている以降のソースも組んでみました。
mobInputTagHelper.php
<?php
function mob_input_tag($name, $value=null, $options = array())
{
$carrier = sfContext::getInstance()->getRequest()->getAttribute('carrier');
if(isset($options['input_style']) && $input_style = strtolower($options['input_style']))
{
unset($options['input_style']);
switch (strtolower($input_style))
{
case 'kana':
$options["mode"] = 'hiragana';
if($carrier != 'docomo')
{
$options['istyle'] = '1';
$options['format'] = '*M';
}
else
{
$options['style'] .= ';-wap-input-format:"*<ja:h>";-wap-input-format:*M;';
}
break;
case 'hankana':
$options["mode"] = 'hankakukana';
if($carrier != 'docomo')
{
$options['istyle'] = '2';
$options['format'] = '*M';
}
else
{
$options['style'] .= ';-wap-input-format:"*<ja:hk>";-wap-input-format:*M;';
}
break;
case 'alpha':
$options["mode"] = 'alphabet';
if($carrier != 'docomo')
{
$options['istyle'] = '3';
$options['format'] = '*m';
}
else
{
$options['style'] .= ';-wap-input-format:"*<ja:en>";-wap-input-format:*m;';
}
break;
case 'numeric':
$options["mode"] = 'numeric';
if($carrier != 'docomo')
{
$options['istyle'] = '4';
$options['format'] = '*N';
}
else
{
$options['style'] .= ';-wap-input-format:"*<ja:n>";-wap-input-format:*N;';
}
break;
}
}
return input_tag($name, $value, $options);
}
作成したカスタムヘルパーは、オートロードされるlibディレクトリ内にhelperというディレクトリを作りその下に配置。
lib/helper/mobInputTagHelper.php
ヘルパーをテンプレートで使用するには、カスタムヘルパーを宣言してロードする必要があります。
<?php use_helper('mobInputTag') ?>
これでテンプレート内でヘルパー関数が使用できます。
// ひらがな
<?php echo mob_input_tag('name', '', array('input_style' => 'kana')) ?>
// 半角カナ
<?php echo mob_input_tag('name', '', array('input_style' => 'hankana')) ?>
// アルファベット
<?php echo mob_input_tag('name', '', array('input_style' => 'alpha')) ?>
// 数字
<?php echo mob_input_tag('name', '', array('input_style' => 'numeric')) ?>
注意点
上記ソースでのいくつか注意点です。
- format属性には半角カナの指定方法がないため、'hankana'オプション指定時にはとりあえず「M」(全角文字)を指定するようになっています。
- 入力モード以外のstyle属性指定にも対応させるよう、-wap-input-formatの前にセミコロンがデフォルトで入るようになってますが、他の指定がある時のみセミコロンを付けるようにしても良いかも。
- このソースはFireMobileSimulatorで出力切り替えを確認したのみで、実機での動作は未確認です。
本来、各キャリアの仕様上では、
docomo
- iモードHTMLはistyle属性、iモードXHTMLは-wap-input-formatをstyle属性
au
- format属性
SoftBank
- mode属性
ということになっているようなのですが、一部の機種依存問題などがあったりすることもあり、こういう冗長的な書き方がバッドノウハウとしてベターなようです。
この辺り、詳しくはスライド作者ゆどうふさんのブログの説明が参考になります。
携帯XHTMLでの入力モードのまとめと、ちょっとしたハマりどころについて - ゆどうふろぐ
また、携帯仕様の資料として以下の書籍も参考にさせて頂きました。
携帯サイト コーディング&デザイン高木 悠介

ソフトバンククリエイティブ 2008-12-26
売り上げランキング : 805
おすすめ平均

Amazonで詳しく見る by G-Tools
symfonyで出力エスケーピング機能を使っている時に生データを出力したい場合、変数であれば
<?php echo $sf_data->getRaw('name') ?>
で出せますが、オブジェクトの値は同じ方法で出すことができません。
テンプレート内で$sf_dataから一旦退避してとか、やり方を調べていたら以下のようにgetRawValueメソッドを使う取り方がありました。
<?php foreach ($members as $member): ?>
<?php echo $member->getRawValue()->getName() ?>
<?php endforeach; ?>
あー、何とか解決。
symfonyは自分が知らないだけで、こうしたいと思ったことの口は大抵用意されてるのでそれを見つけられるかどうかで書き方に差がでますね。
symfonyでライブラリクラスから生成したオブジェクトをserializeして保持する処理を考えていた時の作業録。
You cannot serialize or unserialize PDO instances
まず、オブジェクトをserializeしようとしたら上記エラーが出てしまいました。内部でDBのconnectionを持っている状態でserializeはできないようです。
とりあえず暫定策として__sleep関数を使って、必要なメンバ変数のみ取得できるようにして回避。
public function __sleep()
{
// シリアル化する対象の変数を指定
return array("id", "name", "email");
}
serializeデータにはクラス名と変数の情報しか保持していないので、データをunserializeして使う際にはスクリプト内で事前にクラス定義がされている必要があるようですが(PHP: オブジェクトのシリアル化 - セッションでのオブジェクト - Manual)、symfonyだとオートロードなのでその辺は意識しなくとも使えました。
$unserialize = unserialize($serialize);
//オブジェクトで持っていたメソッドが使える
echo $unserialize->getName();
__sleepで変数指定を調整すればデータ量も最小限に抑えられそうですし、なかなか良さげです。
3日目までは挫折したなりにも以前やったことがあったのですんなりだったが、4日目にしてグっとボリュームが出てきた感じ。
新しく試したキーワードをざっと挙げるだけでも、
- モデルにトリガーメソッドを作成
- パーシャルでフラグメントの整理
- トランザクション
- URLルーティング調整
- カスタムクラス作成
となかなかに盛り沢山。
内容も盛り沢山なので、その分だけわからない点もいくつか出てきた。
例えばInterest.phpのsaveメソッドを修正するところで、いきなり「$this->getQuestion()」が取れてしまうのは何で?schemaの定義に基づいて、modelが関連するQuestionオブジェクトも取得してくれてるってことなのかな。その辺りの自動で済ませてくれている部分が把握できてないと、重複してわざわざ取りに行くようなコードを書いてしまいそう。
ルーティングはかなり柔軟性が高そうで良さげですね。この恩恵を受けるために、テンプレート上のリンクはlink_toヘルパを使うようにすることが大事そう。
カスタムクラス作成でやったタイトルのストリップ処理は、日本語タイトル用にurlencodeするように変えたりしていましたが思うように動いてくれませんでした。これもちょっと課題。
symfonyを入り口近辺でちょろちょろ試してはいたものの、ある程度まとまった知識が欲しいと感じ始めていたので、以前から取り組んではすぐ挫折していたaskeetに再びやることにしました。最低限、24日目まで通してやることが目標。
ちなみにsymfonyバージョンは1.0.19。今から始めるなら1.2系がスジなんでしょうが、askeetチュートリアルもDefinitive Guideも日本語訳が揃っている1.0系に有難く頼らせて頂きたいということで・・・。
1日目
環境構築やプロジェクト、アプリケーションの作成など。
Subversion周りの作業など関係無いところはスキップして、とりあえずさくっと終了。
2日目
DB周りの作業をざーっと行う。
$ symfony propel-generate-crud frontend question Question
上記コマンドでCRUDジェネレータを実行するところで、「Questionモジュールが無い」とエラーになりました。そういえばmodule作成する箇所が無かったような・・・。
というわけで、questionモジュールも先に作成しておきます。
$ symfony init-module frontend question
3日目
レイアウトやテンプレートの変更、ルーティング調整、バッチファイルからのテストデータ取り込みなど。
以下、感じたこと。
- ORMの恩恵受けられるようなDB設計を考慮することが大事。
- ジェネレータでベース作って、不要なアクション・テンプレートをクリーンアップしていくという流れがやっぱり基本?
- css落としてきたけど、なんだかレイアウトずれてるんですが・・・。とりあえず無視。
ひとまず今日はここまで。