PHPの最近のブログ記事
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でライブラリクラスから生成したオブジェクトを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するように変えたりしていましたが思うように動いてくれませんでした。これもちょっと課題。
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 という知らなかったオプションを発見。
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カテゴリー別のランキング表示をできるようにしました。プルダウンからカテゴリーを選択すればそのランキングに表示が切り替わります。お試しください。
読んでる?は小さなサイトではありますが、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