PHPの最近のブログ記事

モバイル開発@symfony :: handsOut.jp

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:&quot;*&lt;ja:h&gt;&quot;;-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:&quot;*&lt;ja:hk&gt;&quot;;-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:&quot;*&lt;ja:en&gt;&quot;;-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:&quot;*&lt;ja:n&gt;&quot;;-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での入力モードのまとめと、ちょっとしたハマりどころについて - ゆどうふろぐ

 

また、携帯仕様の資料として以下の書籍も参考にさせて頂きました。

携帯サイト コーディング&デザイン
高木 悠介

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

Amazonで詳しく見る
by G-Tools

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で変数指定を調整すればデータ量も最小限に抑えられそうですし、なかなか良さげです。

symfonyアドベントカレンダー4日目:リファクタリング

3日目までは挫折したなりにも以前やったことがあったのですんなりだったが、4日目にしてグっとボリュームが出てきた感じ。

新しく試したキーワードをざっと挙げるだけでも、

  • モデルにトリガーメソッドを作成
  • パーシャルでフラグメントの整理
  • トランザクション
  • URLルーティング調整
  • カスタムクラス作成

となかなかに盛り沢山。

内容も盛り沢山なので、その分だけわからない点もいくつか出てきた。

例えばInterest.phpのsaveメソッドを修正するところで、いきなり「$this->getQuestion()」が取れてしまうのは何で?schemaの定義に基づいて、modelが関連するQuestionオブジェクトも取得してくれてるってことなのかな。その辺りの自動で済ませてくれている部分が把握できてないと、重複してわざわざ取りに行くようなコードを書いてしまいそう。

ルーティングはかなり柔軟性が高そうで良さげですね。この恩恵を受けるために、テンプレート上のリンクはlink_toヘルパを使うようにすることが大事そう。

カスタムクラス作成でやったタイトルのストリップ処理は、日本語タイトル用にurlencodeするように変えたりしていましたが思うように動いてくれませんでした。これもちょっと課題。

ORMは便利だろうけど、パフォーマンスが気になるとかSQLが全部目に見える状態で作りたいとかいう話もあったりして、直接PDO経由でDB操作をしたい場合にどうすれば良いのか試してみました。

 

DSN情報を設定ファイルに記述。 

apps/appname/config/app.yml

all:
  db:
    dsn:  mysql:host=localhost;dbname=test
    user: root
    pass: pass

 

DB接続クラスを作成。 

lib/dbConnection.class.php

<?php
class dbConnection
{
  static private $PDOInstance;

  protected function __construct()
  {
    $dsn = sfConfig::get('app_db_dsn');
    $user = sfConfig::get('app_db_user');
    $pass = sfConfig::get('app_db_pass');

    self::$PDOInstance = new PDO($dsn, $user, $pass);
  }

 

  public static function getConnection()
  {
    if(!self::$PDOInstance)
    {
      new self();
    }

 

    return self::$PDOInstance;
  }

}

actionなどからコネクション取得。 

$conn = dbConnection::getConnection();

で、あとはこのコネクション使っていろいろと、ていう感じで動かしてみていたのですが、おいおい調べていたら自作せずともデフォルトのDB設定でPDO接続を指定できてしまうことを知りました・・・。 

 

config/databases.yml

all:
  pdocon:
    class:       sfPDODatabase
    param:
      dsn:       mysql:host=localhost;dbname=test
      dbtype:    mysql
      database:  test
      username:  root
      password: pass

actionからコネクション取得。 

$conn = $this->getContext()->getDatabaseConnection('pdocon');

action以外から取得。 

$conn = sfContext::getInstance()->getDatabaseConnection('pdocon');

 

なるほど、こっちの方が簡単。

動的にDB接続先を切り替えたりといったこともやってみたかったりするので、それぞれの使い勝手も含めて引き続き調べてみたいと思います。

まだ動かして間もないですが、少しずつsymfonyに慣れてきた気がします。

PEARのHTTP_Requestはhttp通信が簡単に行える使い勝手のいいクラスなのでよく使いますが、レスポンスが保証されていないWeb APIとのやり取りなんかでタイムアウト時間を設定したいことがあります。

そんな時にtimeoutオプションを指定してみるのですが、時間通りストップしたりしなかったりと動作が今一つ不安定でした。

Pear パッケージ HTTP_Request - どうにかなるBLOG

こんな記事も見かけたりして、これはいよいよソースに手を加えないとだめかな・・・と思っていたところ、PEAR公式マニュアルを眺めていたら、readTimeout という知らなかったオプションを発見。

Docs For Class HTTP_Request

require_once 'HTTP/Request.php';

$url = "http://www.example.com/";

$option = array(
	"timeout" => 10, // 接続Timeout秒数
	"readTimeout" => 
	array(10, 0) // ソケット読み書きTimeout秒数
);

$http = new HTTP_Request($url, $option);

$http->sendRequest();

$body = $http->getResponseBody();

print_r($body);

おぉ、なんだか期待していたような動き!

それぞれのオプションについては、

  • timeout 通信先とのコネクション確立までのタイムアウト設定(秒
  • readTimeout 接続後のパケットやり取りする時間のタイムアウト設定(秒、ミリ秒)

ということと理解しておきました。

やっぱりマニュアルはちゃんと読まないとな。

前回のエントリーで言っていたAmazonカテゴリー別のランキング表示をできるようにしました。プルダウンからカテゴリーを選択すればそのランキングに表示が切り替わります。お試しください。

Amazonランキング切り替え

読んでる?は小さなサイトではありますが、CodeIgniterで作った初めてのまとも?なサイトでした。引っかかったことなど備忘録代わりにまとめておきます。


URLに日本語をurlencodeした文字列が含まれるとエラーになる

config.phpのpermitted_uri_charsを修正することで解消しました。

//$config['permitted_uri_chars'] = 'a-z 0-9~%.:_-';
$config['permitted_uri_chars'] = '一-龠ぁ-んァ-ヴーa-zA-Z0-9a-z 0-9~%.:_-';
こちらが参考になりました。
   ↓
price-change:blog CodeIgniter | URIで日本語を使うのだ


URIルーティング使うとセグメントのIDがうまく取れない

ルーティング後のセグメント文字列からIDを取得しようとするのですが、思い通りにメソッドへIDが渡されてくれませんでした。マニュアルを調べていたら、URIクラスの説明で

このメソッドは、CodeIgniterのURI ルーティング機能を使っている場合にできる再ルートされた後のURIの特定のセグメントを取得することを除いて、先のメソッドと同じものです。

とあったので、「$this->uri->segment(n)」を使ってIDを取得しておきました。ルーティングした時はURIから取得するという認識で良いのでしょうかね?

3/1(土)に行ってきました。オープンソースカンファレンスに行くのは初めてでした。

最近Codeigniterを少し使うようになったのですが(先日公開した「読んでる?」もCodeigniterで作ってます)、公の場では初お目見え?ということでCI関連に特に注目でした。

CIユーザー会のブースでは、チュートリアルビデオとCIのデモサイト(掲示板、ショッピングサイト)が触れるようになっていました。ブースにいらしたユーザ会の方々ともお話をさせて頂きましたが、業務内で取り入れているケースなどなかなか聞けないようなことも伺えました。私も機会があれば業務で取り入れてみたいと思っていたので参考になりました。

「Codeigniter を使った素敵なプログラミング生活」は、“うまくて、易くて、速いCodeigniter”というタイトルであくまで紹介程度の内容でした。質疑応答でコードが見たい、実例が見たい、といった声がありましたが、セミナールーム内にネットワークが来ていないということで口頭ベースでの説明に留まってしまったのが残念です。(全部屋にLAN引いてください>日本電子専門学校さん)セミナー後、講師の天野さんと名刺交換もさせて頂きました。ありがとうございました。

以下、他にも参加した各セミナーの内容の簡単なメモです。

「45分でわかる Ajax丸かじり」

  • リナックスアカデミー(LA)講師・秦さん。
  • LAの紹介
  • AJAXとは
  • リアルタイム検索サンプル
  • JSONとは
  • リロード抑制サンプル
  • ドラッグ&ドロップサンプル(iGoogle)

「Maple4の設計概要及び今後のMyNETSを活用したWEB Application Platoform構想について

  • 株式会社エムズリンク辻岡さん
  • MyNETSとは
  • OpenPNE2.4から派生したSNS
  • グループ、コミュニティ←→グローバル(mixi、GREE)
  • リソース志向(リソースを集めてコンテンツを構築)
  • Maple4フレームワーク上のアプリケーションプラットフォーム→MyNETS2
  • MyNETS2では現状SNSのリソースは引き継げるようにする
  • 移行ツールの提供
  • 株式会社エムズリンク高橋さん
  • Maple4とは
  • 3→4互換なし
  • ツールだけの提供をしようとしていない
  • Maple4 = TDD x DI x Restful
  • TDD→Test-Driven Development(テスト駆動開発)
  • 開発を楽しく駆動させる→プログラムを書く駆動力
  • 思い通りに動く気持ち良さ
  • 思ったことを先にコードに書く
  • TDDにより細かい責務に分割された大量のクラス
  • DIがクラスを結合、自由自在に組み合わせ
  • Restful→WebのシンプルなメソッドでDIを引き出す

「汎用CMS,Geeklog(ギークログ)をフレームワークとして活用する

  • オープンソース汎用CMS
  • 株式会社アイビー・ウィー今駒さん
  • 自動タグ機能
  • カスタム関数→本体に手を加えずシステムカスタマイズ
  • 自動インストーラができたので簡単導入(Windows)
  • Web巡回ソフトを利用してHTMLファイル生成→静的コンテンツとして公開
  • 本体とカスタマイズ部分が分離しているのでバージョンアップも容易
  • SNS、コミュニティが活発

 

PHPから翻訳したい処理があったので、Google翻訳のソースのぞいて試してみました。

<?php
 // 翻訳するテキスト
 $text = "私は日本人です";
 // 翻訳モード(日→英)
 $enc = "ja|en";
 // 翻訳呼び出し
 $url = "http://translate.google.com/translate_t?langpair=$enc&ie=UTF8&oe=UTF8&text=".urlencode($text);
 $html = file_get_contents($url);
 // テキスト部分取り出し
 $pattern = '/<div id=result_box dir="ltr">(.*?)<\/div>/';
 preg_match($pattern, $html, $matche);
 $trans = $matche[1];
 // 翻訳されたテキスト
 echo $trans;
?>

これを実行すると、

I am Japanese.

なかなか良さげです。

ちなみに翻訳モードのパラメータには、以下のものが使えます。

"ar|en" アラビア語から英語へ
"it|en" イタリア語から英語へ
"nl|en" オランダ語から英語へ
"el|en" ギリシャ語から英語へ
"es|en" スペイン語から英語へ
"de|fr" ドイツ語からフランス語へ
"de|en" ドイツ語から英語へ
"fr|de" フランス語からドイツ語へ
"fr|en" フランス語から英語へ
"pt|en" ポルトガル語から英語へ
"ru|en" ロシア語から英語へ
"en|ar" 英語からアラビア語へ
"en|it" 英語からイタリア語へ
"en|nl" 英語からオランダ語へ
"en|el" 英語からギリシャ語へ
"en|es" 英語からスペイン語へ
"en|de" 英語からドイツ語へ
"en|fr" 英語からフランス語へ
"en|pt" 英語からポルトガル語へ
"en|ru" 英語からロシア語へ
"en|ko" 英語から韓国語へ
"en|zh-CN" 英語から中国語(簡体)へ
"en|zh-TW" 英語から中国語(繁体)へ
"en|ja" 英語から日本語へ
"ko|en" 韓国語から英語へ
"zh|en" 中国語から英語へ
"zh-CN|zh-TW" 中国語(簡体から繁体へ)
"zh-TW|zh-CN" 中国語(繁体から簡体へ)
"ja|en" 日本語から英語へ

 

しかし、パラメータのoe=UTF8が抜けてたのに気付かず結果が文字化けしてばかりで、こんな明け方まで手こずってしまいました・・・。はぁ、寝よ。

 

XREAのサーバを使っていますが、CodeIgniterからPostgreSQL接続しようとすると、CIが次のようなエラーメッセージを吐いて失敗してしまいます。

An Error Was Encountered
Unable to connect to your database server using the provided settings.


接続してる部分のソースをチェックしてみる。
system/database/drivers/postgre/postgre_driver.php を開いて「@pg_pconnect」→「pg_pconnect」に変えて実行すると、

Message: pg_pconnect() [function.pg-pconnect]: Unable to connect to PostgreSQL server: could not connect to server: Connection refused Is the server running on host "localhost" and accepting TCP/IP connections on port 5432?


やっぱり接続時に問題がある模様。
サポートページを調べていたら参考になる記事が見つかりました。
PGSQLへの接続失敗 - XREA&CORE SUPPORT BOARD

つまり、TCP/IP接続でなくソケット経由で接続をしてるので、host、portは指定してはいけないとのこと。
postgre_driver.phpを修正してみます。

return @pg_pconnect("host=".$this->hostname.$port." dbname=".$this->database." user=".$this->username." password=".$this->password);
 ↓
return @pg_pconnect($port." dbname=".$this->database." user=".$this->username." password=".$this->password);


接続できました!

ほんとはdatabase.phpのhostname設定を見てhostを指定するかしないか切り替えれば良いと思いますが、まあ取り急ぎ対応です。

クライアントから文字コードUTF-8でメールフォームのページを作ってくれ、と言うことでPHPでざくっと制作。
セキュリティ上こちらはサーバにアクセスできないので、ファイルをあずけてアップロード~テストはクライアントに確認してもらい、OKが出たのでひとまずそのまま公開。
ところがしばらくして、日本語を送信すると文字化けするとのお知らせが入る。

まあmbstring系の問題だろう、とphp.iniの設定を依頼してもらったところこんな設定になっていましたと。

mbstring.language = Japanese
mbstring.internal_encoding = EUC-JP
mbstring.http_input = auto
mbstring.http_output = SJIS
mbstring.encoding_translation = On


PHPのマニュアルにも同じような設定が載っているので、おそらくそれに合わせたんじゃないかと思われますが、、
これではencoding_translationでパラメータがEUCに自動変換されちゃって、UTF-8を想定して書かれたコードでは化けるわけです。

コードの記述を制限してしまうencoding_translationなんて効かしておく必要ありますかね?
自動変換されるより、自分で文字コード意識しながら書いたほうがよっぽど分かりやすい。

結局、.htaccessを追加で上げてもらって、とりあえず文字化けは解決しました。

php_value mbstring.language Japanese
php_value mbstring.internal_encoding UTF-8
php_value mbstring.http_input pass
php_value mbstring.http_output pass
php_flag mbstring.encoding_translation Off

このアーカイブについて

このページには、過去に書かれたブログ記事のうちPHPカテゴリに属しているものが含まれています。

前のカテゴリはPCです。

次のカテゴリはPostgreSQLです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

RSSフィード

  • 購読する

いろいろ

あわせて読みたい

フィードメーター - ポップフライ

seo

Powered by Movable Type 4.01