symfonyで携帯サイトを作る件

わけあってsymfonyを使ってたら、動的に携帯サイトも対応しなくちゃいけなくなった。

symfonyで携帯サイトをやる情報が少なかったり、プラグインとか重そうだったので、勝手に対応してみた。

これでいいんじゃないかと思う。


symfonyを使って3日くらいしかたってなかったので書き方おかしい???


方針

  • PCサイトも携帯サイトも出来れば一緒
  • テンプレートをPC用と携帯用と2つ作るのはいたしかたなし
  • 絵文字はもともとキャリアごとにiniファイル的なのを作ってたのでそれを使う。
  • 携帯は全てSJIS
  • view.ymlくらいはキャリア毎に分けたい(レイアウトは分けたいし・・・)
  • いざというときtemplateを分けたいかも・・・

というわけで、FilterとViewとHelperを作って対応した。

templates以下にmというモバイル用ディレクトリができて、
m以下にi,y,eという各キャリアごとのディれくトリを作れるようにします。
その他のキャリアはmで吸収?


view.ymlのディレクトリの分け方も同じ。


以下で、動いた。



MobileFilter.php


isFirstCall())
{
// デバッグモードのエラー回避
$er = error_reporting();
if ($er > E_STRICT) {
error_reporting($er - E_STRICT);
}

require_once 'Net/UserAgent/Mobile.php';
$userAgent = Net_UserAgent_Mobile::singleton();

// 出力文字コードを変更する
if ($userAgent->isDoCoMo()
|| $userAgent->isEZweb()
|| $userAgent->isSoftBank())
{
sfConfig::set("sf_charset", "shift_jis");
$this->encordingParams("SJIS", "UTF-8");
mb_internal_encoding('UTF-8');
mb_http_output('SJIS');
ob_start('mb_output_handler');

}

$this->getContext()->getRequest()->setAttribute("userAgent", $userAgent);
}

if ($filterChain)
$filterChain->execute();

}


protected function encordingParams($from, $to) {
if ( $to != "" && $from != "" && $from != $to ) {
$params = $this->getContext()->getRequest()->getParameterHolder()->getNames();

foreach ( $params as $param ) {
$in = $this->getContext()->getRequest()->getParameter($param);
$this->getContext()->getRequest()->setParameter($param, mb_convert_encoding($in, $to, $from));
}
}

}

}
?>



MobileView.class.php


userAgent) {
$this->userAgent = $this->getContext()->getRequest()->getAttribute("userAgent");
}

// store our current view
$actionStackEntry = $this->getContext()->getActionStack()->getLastEntry();
if (!$actionStackEntry->getViewInstance())
{
$actionStackEntry->setViewInstance($this);
}


$default_sf_app_module_config_dir_name = sfConfig::get('sf_app_module_config_dir_name');

$mobile_base_dir = "";
$carrier_dir = "";

if ( !$this->userAgent->isNonMobile() ) {
$mobile_base_dir = "m";

if ($this->userAgent->isDoCoMo()) {
$carrier_dir = "i";
} elseif ($this->userAgent->isEZweb()) {
$carrier_dir = "e";
} elseif ($this->userAgent->isSoftBank()) {
$carrier_dir = "y";
}

$module_config = $default_sf_app_module_config_dir_name . "/" . $mobile_base_dir;

if ($carrier_dir != "") {
$module_config .= '/'.$carrier_dir;
}

sfConfig::set('sf_app_module_config_dir_name',$module_config);
}

$viewConfigFile = sfConfig::get('sf_app_module_config_dir_name').'/view.yml';

// オリジナルの候補はアプリケーションまで
$configFile = sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_module_dir_name').'/'.$this->moduleName.'/'.$viewConfigFile,true);

if ($configFile == null) {
$configFile = sfConfigCache::getInstance()->checkConfig($this->moduleName.'/'.$viewConfigFile,true);
}

if ($configFile == null) {
$configFile = sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app').'/'.$viewConfigFile,true);
}

if ($configFile == null) {
$configFile = sfConfigCache::getInstance()->checkConfig($viewConfigFile, true);
}

if ($configFile == null) {
$error = sprintf('Configuration "%s" does not exist or is unreadable', sfConfig::get('sf_app_module_dir_name').'/'.$viewConfigFile);
throw new sfConfigurationException($error);
}

require($configFile);

// template
if (!$this->directory)
{
$temprates = array();

if ($carrier_dir != "") {
$temprates['carrier'] = $mobile_base_dir . "/" . $carrier_dir."/".$this->template;
}

if ($mobile_base_dir != "") {
$temprates['mobile'] = $mobile_base_dir . "/" . $this->template;
}

$temprates["pc"] = $this->template;

foreach ($temprates as $type => $myTemplate) {
$directry = sfLoader::getTemplateDir($this->moduleName, $myTemplate);
if ($directry) {
$this->setTemplate($myTemplate);
$this->setDirectory($directry);
break;
}
}
}

sfConfig::set('sf_app_module_config_dir_name',$default_sf_app_module_config_dir_name);

$standard_helpers = sfConfig::get('sf_standard_helpers');
$standard_helpers[] = "emoji";

sfConfig::set('sf_standard_helpers', $standard_helpers);
}
}
?>


emojiHelper.php


getEmoji($v);
}

function get_emoji($v)
{
return EmojiHelper::getInstatnce()->getEmoji($v);
}

class EmojiHelper
{

private static $instanse;

private $emoji;

private function __construct($data_dir = "")
{
$userAgent = Net_UserAgent_Mobile::singleton();

if ($userAgent->isDoCoMo()) {
$carrier = "i";
} elseif ($userAgent->isEZweb()) {
$carrier = "e";
} elseif ($userAgent->isSoftBank()) {
$carrier = "y";
} else {
$carrier = "p";
}

if ($data_dir == "") {
$data_dir = dirname(__FILE__)."/data";
}

$data = $data_dir."/".$carrier.".emoji.ini";

$this->emoji = array();
if (file_exists($data)) {
$this->emoji = parse_ini_file($data);
}

}

public static function getInstatnce($data_dir = "")
{
if (!isset(self::$instanse)) {
self::$instanse = new EmojiHelper($data_dir);
}
return self::$instanse;
}

public function getEmoji($key) {
if (!isset($this->emoji[$key])) {
return "";
}

return $this->emoji[$key];
}

}
?>


あとはfilters.ymlとmodule.ymlを書き換えれば使える。

iniファイルの書き方はご自由にすればよい

絵文字を使うときはテンプレートで以下のようにすればよい


p_emoji('hoge')


これでめんどいのは、PC専用モジュールにするときに、いちいち下記のようにしなきゃいけないから、
おなじみのYAMLでなんとかしたいなーーー


public function preExecute()
{
$this->userAgent = $this->getRequest()->getAttribute("userAgent");
$this->forword404if(!$this->userAgent->isNonMobile());
}