メイン

プログラミング アーカイブ

2009年6月24日

PHPで携帯サイトを開発するためのサンプルプログラム本が出ます!

タイトルですべてを言い切ってしまいましたが・・・、「PHP×携帯サイト 実践アプリケーション集」という本が発売になります!執筆したのは私をはじめマイネット・ジャパンのエンジニア陣になります。


PHP×携帯サイト 実践アプリケーション集: 株式会社マイネット・ジャパン, 平島 浩一郎, 伊藤 祐策, 中元 正也
↑できたばっかりのホヤホヤ!


この本は、携帯ブログ、画像投稿写真アルバム、位置情報利用、携帯SNS、といった携帯サイトでよくあるようなWebアプリケーションを、PHPで作るためのサンプルプログラム集になっています。それぞれソースコードが付録CDROMに完全収録されています。
掲載されているサンプルアプリケーションを通じて、文字コードの扱い、絵文字変換、ログイン認証、空メールの受信処理、画像の取り扱い、位置情報、といった携帯サイトならではの処理について、単にソースコードの解説にとどまらず、それぞれの予備知識や実際の運用例にも触れています。紹介しているソースコードは本書のサンプルアプリケーションに限らず他でも扱いやすいようなライブラリ設計になっていて、とくに絵文字処理については、表示、フォーム入力、メール、それぞれでキャリア互換できる変換ライブラリが収録されています。開発者のかたの創意工夫でいろいろ応用してもらえると幸いです。


マイネット・ジャパンでは、携帯サイト作成ASPのkaty(ケイティ)や、その利用店舗を集めた3キャリア公式サイトどこでも!ケイティ、最近はPCだけでなくモバイルも好調なユーザー参加型ニュースサイトnewsing(ニューシング)など、数々の携帯電話向けサイトを開発・運用しています。そのなかで培ってきた開発ノウハウをこの1冊に集結させました。


想定している対象は、PHPでのPC向けウェブサイトの開発経験が多少ある方、としています。PC向けサイトなら開発したことがあるけれど携帯サイトは未経験という方、あるいは携帯サイトをかじったことはあるけれどイマイチ苦手意識が抜けないような方にとって、この本がとてもお役に立てる1冊になるのではないかなと思います!よろしければどうぞ。

 

さらっと目次を紹介すると、こんなラインナップになってます。

  • Chapter 1. PHP携帯サイトへの誘い
  • Chapter 2. RSSニュース表示アプリ
  • Chapter 3. 簡易BBSアプリの開発
  • Chapter 4. 絵文字対応BBSの開発
  • Chapter 5. 携帯ブログの開発
  • Chapter 6. 写メールアルバムの開発
  • Chapter 7. 携帯電話にメールを送る
  • Chapter 8. GPSとWebサービスのマッシュアップ
  • Chapter 9. 携帯SNSアプリの作成

 

アマゾンではこちらから!
Amazon.co.jp: PHP×携帯サイト 実践アプリケーション集: 株式会社マイネット・ジャパン, 平島 浩一郎, 伊藤 祐策, 中元 正也: 本


2009年6月17日

最近になって初めて知ったPHPの基礎のキソ

たまにPHPリファレンスサイトを読み返してみると、知らなかったような超基礎的なことがあるんですねえ。このへんてみんな知ってるような常識? 自分はつい最近まで知らなかったことをいくつか。

 

閉じるタグは省略可能

PHPのコードを書くには <?php ~ ?> の間に書く、というのが基本ですが、このうち終了タグってじつは省略可能です。require()文などで読み込まれるような1ファイルが丸ごとPHPコードのphpファイルの場合は、余計な末尾改行問題を回避するためにもむしろ終了タグ省略が推奨されていたり。

詳細:PHP: 命令の分離 - Manual

 

<script>型指定

PHPのタグというと、前述の <?php ~ ?> のほか、オプションで <? ~ ?> とか <% ~ %> とかが使えますが、このほかにさらに、
<script language="php">
    echo 'Hello World!';
</script>
なんてのも使えます。なんだかクライアントサイドで実行されそうな感じがしますが、他のPHPタグと同様にサーバサイドで処理されてからクライアントのブラウザにHTMLが送信されます。

詳細:PHP: HTML からの脱出 - Manual

 

memory_limitは古いバージョンではデフォルトOff

php.ini で、PHPのメモリ使用量上限値を指定するには memory_limit ディレクティブで指定します。また実行中のスクリプトのメモリ使用量を調べるには、memory_get_usage() があります。これらを利用するには、PHP5.2.1より前のバージョンでは、コンパイル時に --enable-memory-limit オプションをつけないと有効になりません。5.2.1以降だととくに意識せずとも利用できるようになります。

もし有効になっていない場合は、php.iniでメモリ上限を指定したつもりでも、とくにエラーにならずスルーされてしまうので気づきづらい。かなりタチが悪いです。

詳細:PHP: コア php.ini ディレクティブに関する説明 - Manual

 

リフレクション

PHP 5以降では、リフレクションが利用できます。関数とかクラスとか自身の情報が取得できます。フレームワーク的な部分を開発しようとするときなんかに、こういう手段を知ってると痒いところに手が届くかのように重宝しますね。

詳細:PHP: リフレクション - Manual

 

タイプヒンティング

PHPは数値型とか文字列型などが暗黙の型変換されまくりな言語ですが、PHP 5.1以降では、関数の宣言時に引数の型指定がじつはできます。ただしサポートは一部だけで、Object型と配列型のみ。intやstringなどは対象外なのが残念。とはいえうまく活用すれば可読性・保守性の高いコードが書けそうですね。
  public function test_array(array $input_array) {
    print_r($input_array);
  }

詳細:PHP: タイプヒンティング - Manual

 

2008年12月 9日

phpのマニアックな関数

phpってマニアックな関数がいろいろ用意されていて、リファレンスを眺めてると新たな発見がいっぱいあっておもろいです。

 

array_pad

指定長、指定した値で配列を埋める
使用例:
$a = array_pad(array(), 3, 'A');
→ ('A', 'A', 'A')

 

array_fill

配列を指定した値で埋める
使用例:
$a = array_fill(0, 3, 'A');
→ ('A', 'A', 'A')

 

range

ある範囲の整数を有する配列を作成する
使用例:
$a = range('A', 'C');
→ ('A', 'B', 'C')

 

どれもfor文とかでちゃちゃっと自作できてしまう処理ですが、知っておくと得することがある・・・かも。

 

2008年9月29日

MySQL 5.0.42および5.1.18以降で、日付型と日付時刻型とを比較するときの挙動が変更

サーバに入っているMySQLのバージョンを上げたら、それまでなんともなかったところで挙動が変わるようになって原因調べたときの出来事。
MySQL 5.0.42および5.1.18から、MySQL内部の仕様が変更されているそうです。

 

MySQL :: MySQL 5.0 Reference Manual :: 10.3 Date and Time Types

Prior to MySQL 5.0.42, when DATE values are compared with DATETIME values, the time portion of the DATETIME value is ignored, or the comparison could be performed as a string compare. Starting from MySQL 5.0.42, a DATE value is coerced to the DATETIME type by adding the time portion as '00:00:00'. To mimic the old behavior, use the CAST() function to cause the comparison operands to be treated as previously. For example:

date_col = CAST(NOW() AS DATE);

 

MySQL :: MySQL 5.1 Reference Manual :: 10.3 Date and Time Types
こちらの5.1系のリファレンスサイトにも同様のことが書かれています。

 

ざっと訳すと、日付型(YYYY-MM-DD)と日付時刻型(YYYY-MM-DD hh:ii:ss)とで比較をする場合に、以前は日付部分だけをみて比較されていたものが、5.0.42以降は時刻部分も含めた文字列として比較されるようになっていて、その際に日付型は時刻 = 00:00:00 として扱われるため、比較の結果が以前と変わるケースがある。
なので日付型と日付時刻型とをまたいで比較をするときは、明示的にキャストして型変換をしてね。
ということらしい。

NOW() は日付時刻型を返す関数なので、たとえば

WHERE datecolumn = NOW()

なんてやってるとMySQLのバージョンによって比較結果が変わりますよ、と。

 

そもそもは、暗黙的な型変換には頼らずに、つねに型を意識してコードを書いていればこういう問題は起きないわけなのですが。いかんせん暗黙的に動いてしまうコードなので、世の中にも多数埋もれてそうな気がします。

今回、なによりハマったのは、日本語で検索してもなかなか同じような症例がみつからず、日本語版のMySQLリファレンスサイトにもちょうどこの段落だけ記載が抜け落ちていていること!原因がさっぱり見当つかず、しばらく路頭に迷いました。。。

 

2008年5月26日

php勉強会@ノッキングオン

先週の金曜日、php勉強会に参加してきました。

 

http://events.php.gr.jp/event.php/event_show/43

 

これまで何度となく、参加したくても満員御礼なことが続いていたんですが、今回ようやく初参加。

今回のテーマは「モバイル」ということで、GoogleMaps Static APIとかメール配信とかの話がありました。
特別ゲストということでいつもよく見ているke-tai.orgのmatsuiさんがはるばる北海道から来ていて、先日このブログを紹介していただいたお礼を言ったりとか。

 

ひととおり発表が終わったあとの懇親会の中でもさらに発表が始まって、地べたに座って缶ビール飲みながら発表を聞く、というゆるりとした雰囲気が個人的にツボでした。

 

ここ最近のプログラミング言語コミュニティでは、YAPCが開催されたこともありperl界隈の話題がアツいようですが、ひさしぶりにphp使いが集まる場に参加させていただいて、自分ももっともっとphpを深く勉強していこう、なんて思った次第。ヒビ精進です。

 


2008年4月25日

Flex SDKで、Flickrの写真を表示するヤツ

前回にひきつづき、輪講の時間にてFlex SDKに挑戦中です。
Flexならではのものを作りたいよね、ということで、今回はサーバ側との連携に挑戦。
Flexのチュートリアルを眺めていたら、Flickrの画像を持ってくる、というサンプルを見つけたのでこれを叩き台にして試してみたいと思います。

Adobe - Flex Quick Starts: Loading external data with HTTPService

ここに掲載されているソースコードをそのままmxmlファイルとして作成して、前回と同様に mxmlc コマンドでコンパイルすると、こんなswfファイルがすぐに出来上がります。わーい、ちゃんと写真が出てきた!





さて。ここから改造。
この状態で表示される写真はFlickr全体でpublicなもの。どうせなら自分がアップした写真だけを表示させたいですよね。

Flickr のRSS urlの仕様をちょっと調べてみると、

■全員のRSS
http://api.flickr.com/services/feeds/photos_public.gne?lang=en-us&format=rss_200

■指定したユーザーの写真一覧RSS
http://api.flickr.com/services/feeds/photos_public.gne?lang=en-us&format=rss_200&id=(ユーザーID)

という違いがあって、idパラメタでユーザーIDを付加してあげればよいようです。





つぎにFlex側から、任意のurlをコールする方法について。
このチュートリアルに一通りのことが書いてあります。

Adobe - Developer Center : Flex quick start guide for PHP developers

なるほど、<mx:HTTPService>の要素の中に

<mx:request>
   <id>10116145@N03</id>
</mx:request>

といった具合でFlickr ユーザーIDを指定すればOKみたいです。





あと、ついでに見た目の調整も適当にやってしまいましょう。UI部品の色などは、CSSと同じようなプロパティ指定で変更できるようです。
詳細については「flex リファレンス」などで検索すると出てきますが、たとえばこんなものを参考に。

mx.containers.Panel (Flex リファレンスガイド)





そんなこんなで、今回できたのはこんなものです。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    xmlns:aral="*" 
    creationComplete="photoService.send();"
    viewSourceURL="src/HTTPServiceConsumingFlickrRSSFeed/index.html"
>
    <!-- Model -->
    
    <!-- Define the HTTP service -->
    <mx:HTTPService 
        id="photoService"
        url="http://api.flickr.com/services/feeds/photos_public.gne" 
        resultFormat="e4x"
        result="photoResultHandler(event);"
        fault="photoFaultHandler(event);"
    >
      <mx:request>
         <id>10116145@N03</id>
      </mx:request>
   </mx:HTTPService>
    
    <!-- Controller -->
    <mx:Script>
        <![CDATA[
            import flash.net.navigateToURL;
            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            
            [Bindable]

            private var photoFeed:XML;
            
            // Define and use atom namespace.
            private namespace atom = "http://www.w3.org/2005/Atom";
            use namespace atom;
                        
            // The image URL is in the HTML content 
            // so we have to parse it out.
            private function parseImageUrl(fromHtml:XMLList):String
            {
                var pattern:RegExp = /img src="(.+?)" /;
                var results:Array = pattern.exec(fromHtml);
                var imageURL:String = results[1]; // backreference 1 from pattern
                
                return imageURL;
            }

            // Result handler - gets called after RSS is loaded.
            private function photoResultHandler(event:ResultEvent):void
            {
                photoFeed = event.result as XML;
            }
            
            // Fault handler - displays the error.
            private function photoFaultHandler(event:FaultEvent):void
            {
                Alert.show(event.fault.message, "Could not load photo feed");
            }

            // Opens author's HTML page in external window.
            private function openAuthorPage(event:MouseEvent):void
            {
                var dataIndex:uint = Number(event.target.instanceIndices.toString());
                var urlRequest:URLRequest = new URLRequest(photoFeed.entry[dataIndex].author.uri)

                navigateToURL(urlRequest, "_blank");    
            }
        ]]>
    </mx:Script>

    <!-- View -->        

    <!-- Effects -->

    <mx:Fade id="fadeIn" duration="3000" alphaFrom="0" alphaTo="1"/>
    <mx:Fade id="fadeOut" duration="3000" alphaFrom="1" alphaTo="0"/>

    <!-- User Interface -->
    <mx:Panel title="My Photos" width="100%" height="100%" borderColor="blue" backgroundDisabledColor="blue" backgroundColor="#efefff" color="white">
        
        <mx:Tile width="100%" height="100%">            
            <mx:Repeater id="photos" dataProvider="{photoFeed.entry}">                
                <mx:Box 
                    xmlns:mx="http://www.adobe.com/2006/mxml" 
                    textAlign="center" 
                >

                    <mx:Image 
                        id="myImage"
                        source="{parseImageUrl(photos.currentItem.content)}"
                        completeEffect="{fadeIn}"
                        scaleX="0.7"
                        scaleY="0.7"
                    />

                </mx:Box>    
                
            </mx:Repeater>

        </mx:Tile>
        
        <mx:ControlBar horizontalAlign="center">

        </mx:ControlBar>
        
    </mx:Panel>
    
</mx:Application>



これをコンパイルして生成されるswfはこちら。




下記もおなじswfですが、ちっちゃいサイズで貼り付けるとそれだけでブログパーツっぽくなりますね。




2008年4月17日

Adobe Flex SDK超入門

最近の毎週火曜の昼は、輪講と称して、エンジニアで集まってオフィスでお昼ご飯を食べながら、よそのサイトを研究してみたり新しいものをみんなで試してみたりしています。

ここ数回はFlex SDKについて挑戦しています。
自分もまったく知らないところから初めて触ってみたんですが、最初のハードルこそちょっと高く感じたものの、触り始めるとたのしー!ということで、最初にやったことを備忘録がてら「Flex SDK超入門」としてまとめておきます。

 

Flexとは


Flashをベースにした、見た目がかっこいい(=リッチなインタフェースの)webアプリケーションが開発できるフレームワーク、です。(自分も全て理解し切れていないのでこの表現は正確ではないかも。。)
Flexを使うとこんなものが作れます、というサンプルがadobeのサイトにあります。たとえばこんなの。

Tシャツのデザインをカスタマイズできるもの

Dashboard。グラフ表示のパーツを並べたもの。こういったGUIコンポーネントが多数用意されている。

 

現在の最新バージョンはFlex 3。web上の情報を探すと古いバージョンを元にした記事が多数ありますが、試した範囲では互換性保たれている模様。

 

Flexで開発するには


方法がいくつかあります。

●Flex Builderを使う
Flex開発するためのIDE(統合開発環境)ソフトです。もっとも標準的な方法。有償(60日間の無料体験版あり)。

●Flex SDKを使う
mxmlファイルをテキストエディタで編集して、コンパイルしてswfを吐き出すやり方。無償。
mxmlファイルとは、ActionScriptのプログラムコードやGUIパーツの配置座標情報などを含んだ、xml形式のファイルです。ActionScriptコードは、xmlのCDATA要素の中に記述します。

 

今回は、Flex SDKをつかって開発を試してみます。

 

Flex SDKのセットアップ


SDKをアドビのサイトからダウンロードすればいいわけなんですが、これがとてもわかりづらいところにあります。(たぶんここがハードル一番高い、と思う。。)

■Flex 3 SDKのダウンロード
Adobe - Download Adobe Flex 3

このページの上半分は有償版 Flex Builderのダウンロードなのでここはスルーして、下半分を見ましょう。「ライセンスに同意」のチェックボックスをONにすると初めて、ダウンロードのテキストリンクがアクティブになります。

 

20080417flexsdkdownload.png

 

ダウンロードが終わったら、解凍してどこか好きなディレクトリにおいておきます。

 

あと、Flex実行にはJava実行環境が必要です。まだインストールされていない場合はこちらからダウンロード&インストールしておきます。

http://java.sun.com/javase/ja/6/download.html
※このページの「JDK 6 Update 6」で。(2008.04.17時点)

 

Flex SDKでHello World


まずは手始めに、mxmlファイルをテキストエディタで作って、それをコンパイルしてswfファイルを作って、表示を確認してみましょう。

こちらのサイトにあるチュートリアルにのっとった内容です。

 

●テキストエディタでこのような内容のファイルを作ります。保存名はMyFirst.mxmlとでも。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    horizontalAlign="center" verticalAlign="center">

    <mx:Button id="myButton" label="I'm a button!" />
</mx:Application>

●これをコンパイル

コンパイラは、ダウンロードしたSDKを解凍した中にある、bin/mxmlc.exe です。 Windowsのコマンドプロンプト上で

mxmlc --strict=true --file-specs MyFirst.mxml

こんな感じで実行します。

☆オプションは指定しなくてもコンパイルは可能。下記でもOK。

mxmlc MyFirst.mxml

☆コマンドプロンプトでパスを通す。
みんなでやってたら「パスが通らない」っつって詰まる人がちらほらいたんですが、エクスプローラ上のファイルをコマンドプロンプトへドラッグすると、フルパス文字列でプロンプト上に持ってこれます。(常識かと思っていたが意外とそうでもない?)

 

コンパイルが終わると(数秒ほどかかります)、MyFirst.mxml ファイルがあった同じディレクトリに MyFirst.swf が生成されているはずです。これをブラウザウインドウにドラッグなどすると、内容が表示されます。ボタンが表示されるだけ、のものです。


 

 

と、ここまで、超入門編でした。
アドビのチュートリアルページにはこのあと、ボタンにonclickアクションを定義したり、GUI部品を配置するときの座標系の話、他の画像ファイルやswfファイルなどを埋め込むやり方、などが解説されているのでどうぞー。

 

Flexクイックスタート - Adobe デベロッパーセンター

 

2008年4月14日

iモードHTMLシミュレータとiモードID

いつも気がついたらアップデートされているドコモ提供のiモードHTMLシミュレータですが、dcmguidをつかった処理を作ってみようかな、というついでにチェックしてみたら、シミュレータではまだiモードIDに未対応のまま、でした。
#しゃぁねえな、実機でやるしかないかー。。。

 

とはいえ現在の最新バージョンは5.1で、2007年10月に更新されたもの。手元にあったやつはもっと古かったのでとりあえずはダウンロードしなおし、っと。

 

2008年4月 8日

【php&ethnaで携帯サイトを作る】セッション管理(その3)

世の中はすっかりEthnaよりもCakePHPだよなー、なんて思いつつ。マイペースにこのシリーズ続けます。携帯サイト向けのセッション管理のお話。
ちょうど今月よりドコモでもimodeIDが取得できるようになったので、こういうセッション管理は今後必要なくなるかもしれないですが・・・。
今回はethnaに依存した話です。

 

session.use_cookies の変更タイミング

前々回で、php.ini設定項目の session.use_cookies を変更するとかって話をしましたが、今回はそれをどうethnaプロジェクトに実装するか、という話。

session.use_cookies の値を動的に変更するには、session_start() をするまえに変更しないと意味がないようです。これを実装する1つの方法として、Ethna_Sessionクラスを継承したクラスを作って、そのコンストラクタに記述する手があります。親クラスのコンストラクタを呼んだ直後に記述するとうまくいきました。
あ、Ethna_Sessionクラスを上書きする場合名、appディレクトリ直下の Controller.php でその名前を指定するのを忘れずに。

 

セッションパラメタ名の変更タイミング

続いてセッションパラメタ名を変更する場合の記述箇所について。「PHPSESSID=xxxx」ってやつを任意のものに変更する場合ですね。
これも上記と同じく、session_start() をする前、Ethna_Session 継承クラスのコンストラクタに記述するのがよいようです。

そんなわけで上記2つをあわせて、サンプルとしてはこんなものになります。

class Session_Extends extends Ethna_Session_Memcache
{
    function Session_Extends($appid, $save_dir, $logger)
    {
        //■親クラスのコンストラクタをコール
        parent::Ethna_Session($appid, $save_dir, $logger);
        
        //■セッション名を上書き
        $sessname = 'PHPSESSID';    //任意のものに変更
        $this->session_name = $sessname;
        session_name($this->session_name);
        
        //■クッキーが使えない端末からのアクセスのときは、urlパラメタでセッション引数を引き回すようにする
        if(Mobile::isEnableCookie() == false)
        {
            ini_set('session.use_cookies', 0);
        }
    }
}

 

Ethna_sessionのおせっかい機能

セッション使用時は、毎回アクセスもとのIPアドレスをチェックして、前回とちがうIPからアクセスされてきたときは別セッションとみなしてセッションを再スタートさせる処理、が、Ethna_Sessionに実装されています。PCアクセスの場合は頼りになる処理なんですが、携帯アクセスのときはコレが余計なお世話。携帯電話の場合、アクセスするたびにIPアドレスは変わりうるので、このままではセッションが継続されません。 ので、この実装を打ち消す対応が必要です。 具体的には、Ethna_session のなかの _validateRemoteAddr() が、このIPアドレスのチェックを行っています。このメソッドを、常にtrueを返すようにオーバーライドすればOKです。

 

 

過去のシリーズ記事

 

2008年3月31日

ドコモ(docomo)端末でiモードIDの通知が開始

今日からコレが開始です。

重要なお知らせ : 『iモードID』の提供開始について | お知らせ | NTTドコモ

ドコモは、お客様の利便性・満足の向上と、「iモード®」対応サイトの機能拡充を図るため、iモード上で閲覧可能な全てのサイトへの提供を可能としたユーザID『iモードID』(以下、iモードID)機能を提供いたします。

iモードIDについて - 作ろうiモードコンテンツ

 

さっそく試してみました。phpだとこんなやり方で取得OK。

echo $_SERVER['HTTP_X_DCMGUID'];

試してみた端末では、iモードIDの値は英数大文字小文字交じりの7文字でした。

 

注意点は、上記サイトに書いてありますが、

  • アクセスするときのurlに「guid=on」をつける。GET/POSTどちらもOK。

  • httpアクセスのときのみ有効(!)。httpsアクセスでは利用できませんでした。

  • 端末側のデフォルト設定はON。

 

2008年3月28日

【php&ethnaで携帯サイトを作る】セッション管理(その2)

週1ペースで書く、なんて宣言しておきながら2ヶ月以上ほったらかしにしているこのシリーズですが、、、しれっと続きをいきましょう。

 

前回の続きで、クッキーが使えない携帯端末向けのサイトでセッション管理をするときの話、です。

 

定数SID

セッションIDを url に埋め込むのに、php.ini 設定の session.use_cookies を操作するのではなく、自力でphpで処理を書く場合。定数 SID というのが使えます。
この定数、自分も最近まで存在を知らなかったんですが、PHPリファレンスサイトのなかの http://jp2.php.net/manual/ja/ref.session.php#session.idpassing や、同じページのなかの「定義済み定数」の欄に説明が書いてあります。

セッションが開始している場合に定義されている定数 SID を使用することもできます。クライアントが適当な セッションクッキーを送信しなかった場合、この定数は session_name=session_id の形式となります。 他方、送信された場合には、この定数は空の文字列に展開されます。 このため、この定数を無条件に URL に埋め込むことができます。

 

ということで、url にセッションIDを付加する処理を自分で書く場合は、このSID定数を見て、 ? なり & なりで url の後ろにつなげるのが良いです。
あ、かるくハマっことあるのは url の中に「#hoge」っていうアンカーが含まれている場合。この場合は末尾に付加するとアンカーテキストの一部と見なされてしまうので、# の前に付加するようにしましょう。

 

セッションの有効期限の管理

セッションの有効期限を、「ブラウザ閉じるまで」のセッションクッキーではなく、時間指定で期限設定したい場合の話。

cookieでセッション管理する場合は、cookie自身に有効期限を設定できるのでこれで管理すればOKなのですが、urlパラメタで管理する場合、このクッキー有効期限のしくみは利用できません。

ので別の手段で期限管理をする必要があるわけですが、自分が思いついたのは、セッション変数としてパラメタ管理する方法。有効期限の値をセッション変数のなかで保持するようにすれば、この問題は回避OKです。

 

mod_rewriteリライトルール

これはちょっとレアケースだと思いますが、、mod_rewriteでurlのリライトを行っている場合の話。

RewriteRuleの記述で、クエリストリングを引き継がない設定になっている場合、すなわり「QSA」オプションの記述がない場合は、せっかくurlに付加したセッションIDがリライトしたときに消えてしまってなぜかセッションが切れる、ということでハマったことがありました。

 

 

 

セッション管理の話はもう1回だけ続く予定です。ここまでphp全般の話題をしてきましたが、次回はethnaと関わる話をしようかなと。。。→書きました

 

過去のシリーズ記事

 

2008年2月22日

SmartyでどうしてもShift_JISを使いたいときのバッド?ノウハウ

phpのテンプレートエンジンSmartyは、ソースファイルの文字エンコーディングをeucで書くことが推奨されています。Shift_JIS (SJIS)で作成すると、文字によっては文字化けしてしまいます。これは全角文字の2バイト目に、Smartyのデリミタ文字である中カッコ { , } と同じバイトが含まれてしまうため。

これが「特定の文字」だけで発生するので微妙に性質が悪い。
途中まで気づかずに開発してきて、終盤になって「うっわ、文字化けしてんじゃん」「やべー今まで全部ShiftJISで作ってきたのに」「いまさら全部文字コード変えるの面倒くせぇ」というシチュエーション。

そんなときに、その特定の文字での文字化け箇所だけを簡単に回避する技。

 

その箇所を {literal} ~ {/literal} で囲みましょう。

 

{literal} でくくると、その間は中カッコ{}が普通に使えるようになるので、つまりShift_JISでの文字化けの原因も起きません。と、理論上で考えて試してみたら実際に解決できたので我ながらナイスアイデア。

とはいえこんな方法保障しませんよ。その場しのぎで対応したいときにもしかしたら使えるかも。程度に。

 

2008年1月15日

【php&ethnaで携帯サイトを作る】セッション管理(前編)

さて、1週間ぶりにこのシリーズ再開。
#正月の間に下書きしておいた記事ストックがなくなったから、というのはここだけの話w。今後は週1くらいのペースを目標に続けていきます。。

ということで今回は、ログインをしてセッション管理が必要なサイトを作るときの話です。

 

携帯サイトではCookieが使えない。

大きく立ちはだかるのが、Cookie使えない壁です。imode端末のすべてとソフトバンクの一部機種(C型・P型)がCookieに対応していません。auはOKなんだけどね。
なのでCookieが使えないなら、urlパラメタにセッションキーをいれてずっと引き継いでいくことになります。

PHPの機能

php.iniの設定で操作できることに、次の2つがあります。

session.use_cookies

session.use_cookiesによりクライアント側にセッションIDを保存する際にクッキーを使用するかどうかを指定します。デフォルトは1(有効)です。

このオプションを0(無効)にすると、クッキーではなくurlパラメタで、セッションキーを引き回せるようになります。もうすこし厳密に言うと、urlパラメタに PHPSESSID=xxxxxx があると、このセッションキーからひもづいてwwwサーバ側に保存されているセッション変数群に $_SESSION[] でアクセスできるよう、PHP言語側で処理してくれるようになります。

session.use_trans_sid

session.use_trans_sidは、透過的なセッションIDの付加をするかどうかを指定します。デフォルトは、0(無効)です。

これ、くわしい挙動を確認してみたところ、こんな動きをしてくれます。

phpファイル中に書かれているすべての<a href="hoge">の記述について、(<a>タグだけでなく<form>なども処理対象です)

  • urlが絶対パスの場合 → なにもしない

  • urlが相対パスの場合 → 自動的にurl末尾に「?PHPSESSID=xxxxxx」を付加してくれる。(ほかにパラメタがすでに記述されている場合は?ではなく&でつなげられます)

なかなか便利そうーと最初は思ったんですが、いざ使ってみるとなかなか扱いが面倒になるケースがあるので、私はこのオプションは利用しない派。代わりにSmartyの修正子で似たような処理を作る方向でも対応可能かと。

(そのほか、関連項目にsession.use_only_cookiesとかurl_rewriter.tagsとかがありますので興味のある方はどうぞ。)

で、これらのphp.iniの設定項目は、コード中でphp_ini()関数で動的に変更できるので、UAなどを見てCookie非対応機種からアクセスされたときはこれらのオプションを変更する、という手が取れます。

セッションパラメタ名

上記で PHPSESSID と記述しているセッションパラメタ名ですが、これはデフォルト設定で、session_name()関数で自由に設定できます。デフォルトだとカッコわるいwので適宜変えちゃいましょう。

その際の注意ポイントですが、

  • docomoで、urlの文字長は最大512バイトまで。
    なのでなるべく短いのにしましょう。

  • Softbankで、公式サイト以外では使ってはいけないパラメタ名というのが定められていて、「sid」「uid」とかのベタなやつは使っちゃダメってことになっています。(詳しくはソフトバンク公式技術サイト「HTML編」のP.51あたり)

 

 

長くなってきたので後編に続く。

 

2008年1月 9日

【php&ethnaで携帯サイトを作る】文字コード変換処理

携帯サイトhtmlの文字エンコーディングはShift_JISにするのが良いわけですが、ethnaに取り込まれているsmartyがEUC-JP推奨になっていて、Shift_JISだと内容によってsmartyがエラーを吐く場合があります(UTF-8なら問題は起きない、という情報もアリ。ジブンは未確認)。

そこで、ソースコードやテンプレートファイルはすべてEUC-JPで書いておいて、出力するときにShift_JISに変換して出力する、というやり方が良いです。
ethnaには入出力時に自動で任意の処理を行うフィルタ(filter)のしくみが用意されているので、これを用いるとコード中で文字コード変換する処理を極力減らすことができてすっきりします。

また出力時だけでなく、POSTされたデータを受け取るときの処理も同様です。フォーム入力されてPOSTされた日本語データは、元ページhtmlの文字エンコーディングのままで送られてきます(ただし例外アリ。auの場合、UTF-8でページを作っていても送られてくるデータはShift_JISの場合があります)。それをコード内で処理したりDBに格納したりするときの文字エンコーディングを統一させるのに、filterをつかうことでスッキリと処理できるようになります。

 

filterを使うには、ethnaプロジェクトディレクトリの app/filter/ のなかにfilterファイルを作って、Controllerの中にfilter名を記述すればOKです。

 

以下、filterの記述例です。
ソースコード自体はeucで記述しておいて、携帯からアクセスされた場合はShiftJISで、PCからアクセスされた場合はそのままeucで出力させるケースです。
中で使用しているNet_UserAgent_Mobileについてはこのへんとかを参照ください。

 

include_once('Net/UserAgent/Mobile.php'); 

class Hoge_Filter extends Ethna_Filter
{
// POSTされたデータを文字コード変換してからソースコード本体に渡す
function preFilter()
{
ob_start();

$agent = Net_UserAgent_Mobile::singleton();
if($agent->isDoCoMo() || $agent->isEZweb() || $agent->isVodafone())
{
//■携帯アクセスの場合は、受け取りパラメタのエンコードをsjis->euc変換
$_GET = Filter_convert_encoding_sjis2euc($_GET);
$_POST = Filter_convert_encoding_sjis2euc($_POST);
}
else
{
//■PCアクセスの場合はなにもしない
}
}

// 出力時に文字コード変換処理を行う(smarty変換処理のあとにコールされる)
function postFilter()
{
$content = ob_get_contents();

$agent = Net_UserAgent_Mobile::singleton();
if($agent->isDoCoMo() || $agent->isEZweb() || $agent->isVodafone())
{
//■携帯アクセスの場合

//xhtmlの場合はここでContent-Typeを出力
//header('Content-Type: application/xhtml+xml; charset=Shift-JIS;');

//エンコーディングをShiftJISに変換
$content = mb_convert_encoding($content, 'sjis-win', 'eucJP-win');
}
else
{
//■PCアクセスの場合はなにもしない
}

ob_clean();
echo $content;
ob_end_flush();
}
}

// 引数が配列の場合は中の要素を再帰的に処理
function Filter_convert_encoding_sjis2euc($value)
{
if(is_array($value))
{
return array_map('Filter_convert_encoding_sjis2euc', $value);
}
else
{
return mb_convert_encoding($value, 'eucjp-win', 'sjis-win');
}
}

 

ポイントはob_start()を使って出力をいったんバッファに入れておいて、最後に全部まとめて文字コード変換してから出力する、というやりかた。
これを記述しておくと、煩雑になりがちな文字コード変換処理を自動で行ってくれて、ソースコード本体がシンプルになって開発効率も向上!すると思います。超おすすめ。

・・って、エラそうに書いてますがWEB+DB PRESS 37に掲載されていたウノウさんのコードをかなり参考にさせていただいています。感謝。

 

ちなみにこのethna filterを使わなくとも、ob_start()とob_get_contents()あたりを組み合わせて使うと同様の処理が実現できるとおもいます。

2008年1月 8日

【php&ethnaで携帯サイトを作る】ケータイサイト開発のおさらい

まずは基本的なところのおさらいから。
こまかく言い出すとキリがないのでさらっと。おもにPCでのweb開発しかやったことないひと向けに書いていきます。


html/xhtml

PCと似ているようで結構違う。キャリアによっても機種によってもサポート状況に違いあり。
開発するサイトがターゲットにする端末範囲を要件定義した上で、使えるタグのみを利用していくのが吉。
違いの大きなところだと
・ちょっと古い機種ではtableタグ使えない
・テキストの背景色指定をするには、tableタグかxhtml+cssが必要
・文字の大きさ指定も端末によって差の幅アリ。端末側のデフォルト文字サイズ設定にも大きく左右される
・formまわりの記述も端末による違いに注意が必要。また文字入力モードを指定するistyle属性を忘れずに記述しておくと使い勝手が格段に向上します


文字コード

ShiftJISで作るのが良いです。
xhtmlだとUTF8やeucでもいける端末もあります。
POSTされた日本語データの受け取り処理時に、どの文字コードでPOSTされて来たか留意しましょう。


画像

最近の機種だとどれもgif/jpgが表示できるのであまり気にしなくて良いが、古い端末だと機種・キャリアによってサポートしていない形式があり、キャリアによって出し分けする必要アリ。
形式はもとより、容量制限(1ページあたり10KB以内、など機種によりさまざま)もギリギリになりやすい。


絵文字

とにかく鬼門になるのが絵文字対応。これは別エントリーにまとめます。


クッキー

ドコモ機種はcookieが使えません。auと一部のソフトバンク機種はcookie対応。
cookie使えない機種でセッション管理をするには、urlのクエリパラメタにセッションキーを付け回す必要アリ。


JavaScript

いまのところ一切使えません。
Ajaxでフォームを動的に書き換えることに慣れた身体にはえらく自由度が低くて困ります。。
また、katy(ケイティ)のユーザーサポートをしていて時々問い合わせを受けるんですが、Google AnalyticsなどのJava Scriptをつかったアクセス解析サービス等も携帯では一切使えません。


Flash

簡易版のFlash liteが、使える端末があります。
Flash liteは今まさに大きく進化中で、搭載されているFlash Playerのバージョンによって、実現可能なことが大きく異なります。


携帯限定のサイトにするには

携帯端末からのアクセスのみに限定して、PCからのアクセスを受け付けなくする手法がよくとられます。
理由はいろいろあると思いますが、コミュニティ運営上の理由で携帯ユーザー限定にしたりとか、htmlソースが見れないなど自由度の低い携帯ブラウザからのアクセスに絞ることでのセキュリティ上の理由だったり。

やり方としてはおおきく2つ。
UserAgentで判別
携帯端末からのアクセスは、判別可能なUserAgent情報があるので、それで判定する方法。
短所としては、PCブラウザでもUAを詐称するとアクセス可能になること。
IPで判別
携帯電話からのアクセスは、アクセス元IPアドレスの範囲が決まっている(各キャリアが公開しています)ので、このIPアドレスから以外のアクセスは受け付けなくする方法。
サイト側でこの方法をとっている場合、PCからのアクセスはどうあがいても不能です。
短所は、このIP範囲帯はたまに変更されるので保守し続ける必要があること。

 

2008年1月 7日

【php&ethnaで携帯サイトを作る】序章

さて。突然ですが、「php&ethnaで携帯サイトを作る」と題したエントリーをこれから数回にわたって書いていこうと思います。

 

このところいくつかの開発案件で、フレームワークethnaを使ってケータイサイトを作ることを続けてやっていて、ちょっぴりですがノウハウ的なものがたまってきたので、このまま忘れてしまう前にブログにでも書き残しておこう、というシリーズです。

ケータイサイトを開発するにあたって、シロート状態のところからいろんな情報をたよりにこれまでやってきました。
キャリアや機種によって差異があまりにありすぎて、検索して見つけた情報がその通りに動かないじゃん!なんて目に何度も遭いつつ。
これから書いてく内容も完全にすべての機種で動作確認をしているわけではないので、他の情報と同じように場合によっては正しく動かないこともあるかもしれません。時代が流れるにつれてあたらしい機種端末も次々出てきて情報も劣化していくと思います。
とはいえ、ただでさえあまりまとまっていない携帯サイト開発に必要な情報をちょっとでもまとめることで、他の人のお役に少しでも立てれば、と思います。
#あと、自分も知らないことがまだまだたくさんあるので識者のかたに教えてもらえれば。^^

 

表題に「ethnaで」と書いているとおり、ethnaフレームワークをつかった場合の話が時々紛れ込んでくると思いますが、必ずしもethnaに限った話ばかりではないのでethna onlyな箇所については適宜読み替えていけばethna不使用の場合でも十分通用するかと思います。

 

2007年12月18日

ianime.jsを使ってみた。

以前会社に遊びに来ていただいたこともあるLife is beautiful中島さんが、面白そうなJavaScriptアニメーションライブラリを作っているのをみて、ためしに使ってみたくなった。
ということでマイネット・ジャパン社内フォトアルバム的なものをささっと。

 

 

今回は中島さんのサンプルコードほとんどそのまんまですが、コツをつかむといろんなものがすぐにさくさく実現できそうですね。
これ系のエフェクトを作りたいときは、これまでrico.jsやscript.aculo.usなんかを使うことが多かったですが、どちらも重いライブラリなのでなかなかためらわれることもしばしば。それに引きかえiAnime.jsはかなり軽いのでなにかと重宝しそうです。動作の定義がキレイに書けるので、いろいろ今後の拡張性も楽しそう。


2007年12月17日

imodeサイトでページ内アンカー<a name="hoge">が効かない

調べてみたらxhtmlの常識?だったぽい。えーそんなの知らなかったよ!

 

【本日のハマりポイント】
<a name="hoge">を作っておいて(url)#hogeへアクセスすると、imodeだとページ内移動が行われない。

 

【ちょっとぐぐったらすぐに答え見つかった】
この症状が起きるのはimodeでxhtmlサイトの場合のみ。
name属性は、xhtmlでは不採用で、代わりにid属性が推奨。
なので、<a name="hoge" id="hoge">と書くのが正解みたいです。これだとちゃんと動く。

 

ちなみに、他の携帯端末やPCブラウザでは、xhtmlサイトでも<a name="hoge">だけでちゃんと動いてくれるようです。

 

2007年10月31日

短いJavaScriptコードでテトリス

newsing(ニューシング)経由で知ったネタですが、初代スーパーマリオブラザースは、容量が40KBしかなかった、というお話。

 

往年の名作「スーパーマリオブラザーズ」、あの濃い内容でわずか40キロバイト - newsing(ニューシング)
■元ネタ:痛いニュース(ノ∀`):往年の名作「スーパーマリオブラザーズ」、あの濃い内容でわずか40キロバイト
■さらに元ネタ:ITmedia +D Games:レトロゲーム・アワード受賞! 「スーパーマリオブラザーズ」

これだけ濃い内容なのに、データ容量はわずか320キロビット、つまり40キロバイトということに驚く。今の携帯電話のゲームだって、短いものでも150キロバイトくらいはある。

 

ジブンもかつて一時期、ソースファイルの容量や、コンパイル後のバイナリファイルの容量をできる限り削ることに情熱を燃やしてたことがあったなー、と若い頃を回想。
はい、「痛いニュース」でいろいろ言われてますが、たしかにファイルサイズ容量とコンテンツの面白さはまったく関係がなくて、容量を削ろうとするモチベーションは、ハードウェア的な制約か、開発者の偏った情熱(?)か、どちらかがあって初めて成り立つもののような気がします。

 

で。
「痛いニュース」のなかで紹介されていた、JavaScriptの短いコードでテトリスが動く、というのが「へーー!」でした。
コードはこれだけ。コード容量は1KB以下。

<body onKeyDown=K=event.keyCode><script>X=[Z=[B=A=12]];h=e=K=t=P=0;function Y()
{C=[d=K-38];c=0;for(i=4;i--*K;K-13?c+=!Z[h+p+d]:c-=!Z[h+(C[i]=p*A-Math.round(p/
A)*145)])p=B[i];!t|c+4?c-4?0:h+=d:B=C;for(f=K=i=0;i<4;f+=Z[A+p])X[p=h+B[i++]]=1
if(e=!e){if(f|B){for(l=228;i--;)Z[h+B[i]]=k=1;for(B=[[-7,-20,6,17,-9,3,6][t=++t
%7]-4,0,1,t-6?-A:-1];l--;h=5)if(l%A)l-=l%A*!Z[l];else for(P+=k++,j=l+=A;--j>A;)
Z[j]=Z[j-A]}h+=A}for(i=S="";i<240;X[i]=Z[i]|=++i%A<2|i>228)i%A?0:S+="<br>",S+=X
[i]?"■":"_";document.body.innerHTML=S+P;Z[5]||setTimeout(Y,99-P)}Y()</script>

これが、こんなかんじで動きます。これはすごいっすねー。



カーソル左右で移動
enterキーで回転

 

2007年8月 6日

軍議night 8/3

マイネット・ジャパンでは、以前から週1回「軍議night」と称して、社内エンジニア+@のメンバーでこじんまりと勉強会をしています。
今回はひさびさの自分の番だったので、ちょうど先週リリースしたばかりのkaty(ケイティ)メールプランに関して、その裏側の処理について紹介をしました。

 

かんたんな議事録をこちらに書きましたので、興味のあるかたはどーぞ。

 

2007年3月13日

ブラウザ差につよいCSSの書き方

先日初めてお会いして、仲良くなった(と一方的に思っている)エスカフラーチェのpurprinさんが、CSS Niteの資料を公開されてます。

 

[CSSNite in Nagoya 2007] 極力ハックしない CSS というテーマでお話しました - pur*log

 

 

えらい大ボリュームの力作。
ネタもさることながら、すごく分かりやすくまとまっていて、これはよいベンキョウ材料になりそうです。
ブラウザによるCSSのレンダリング差は、自分も経験的にしか分かってなかったりするので、コレのように整理されたものはとても有り難いです。あ、これジブンもハマったことある!的なネタが盛りだくさん。
 
事前に自慢していた緑色のレーザーポインタもフル活用したんでしょうか。ともあれ、おつかれさまでした。

 

2006年12月19日

webエンジニアが抑えておくべき、htmlデザインの6つのポイント

「htmlのことはなんとなくはだいたい知ってるよ」というエンジニアが、初めて業務でhtmlコーディングをするときにわりとハマりやすい点。ぐぐってもあまり出てこないような細かいノウハウをまとめてみました。

 

ウインドウ余白を消したい

ブラウザによっては、ウインドウ枠のまわりに余白スペースが挿入されてしまって、ウインドウの端まで画像等を配置したいのに実現できない、なんてことがあります。これはbodyタグがデフォルトで余白を持っているのが原因です。
<body leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">

と記述するか、あるいはcssで

<body style="margin:0;padding:0;">

として、余計なマージンを消してしまいましょう。

 

formタグをいれると空行があいてしまう。

<form>タグを入れた箇所で、勝手に1行分の余計なスペースが入ってしまってレイアウトが崩れてしまうことがよくあります。 回避するには、
<form style="margin:0;padding:0;">

として、CSSレベルでプリセットされているマージンやパディングを消してやると良いです。

 

テキストフォームとパスワードフォームの大きさ違い

ログインフォームなどをつくるときに、IDとパスワードを入れる欄を並べることがよくあります。このとき、
<input type="text" size="20"><br>
<input type="password" size="20"><br>

と書いてしまうと、IEで見るとなぜか両者の横幅が異なってしまいます。これはちょっとかっこわるい。

ので、下記のようにcssで横幅指定すると吉です。

<input type="text"style="width:100px;"><br>
<input type="password" style="width:100px;"><br>

 

画像にはalt属性を

<img>タグにはalt属性を必須でつけるのが正しいhtmlコーディングです。けっこう忘れがち。<自分

 

imgタグ画像と背景画像

画像を表示させるには、imgタグを使う方法と、他の要素の背景画像として指定する方法とがあります。

どちらもブラウザでの見た目に違いはないですが、紙にプリントするとおおきく異なることがあります。ブラウザの設定によっては、imgタグで指定した画像は印刷されますが、背景画像として指定したものは印刷されません。

 

<a>タグを使いたいが、リンク先は指定したくない。

開発している最中によくありますが、テキストリンクを張りたいがまだリンク先urlが決まっていないときの話。
<a>こちら</a>へ

という記述をすると、文字色が青くなったりアンダーラインがついたりといったいつものビジュアル変化がなにも起きず、開発していくのに都合のよろしくないことになったりします。

<a href="">こちら</a>へ

と書くとビジュアルはちゃんと変化しますが、リンク部分をクリックすると意図しないページへ遷移してしまってまた効率が悪かったり。

こんなとき、ジブンが良く使うのは次の2パターン。

<a href="#">こちら</a>へ

webデザイナーの人がよく使う手。リンク部分をクリックしてもページは遷移しません。
が、別のurlへアクセスすることになるので、クリックしたあとブラウザの「戻る」をするときは1回余計にクリックする必要アリ。

<a href="javasacsript:void(0);">こちら</a>へ

こうするとビジュアルもちゃんと変化して、クリックしてもなにも起きません。

 

 

2006年10月27日

ブックマークレットをつくってみた。いま見ているページのtitleをコピペしたい。

ブログを書いてて、他のページへのリンクを作る操作がわずらわしくてたまらないので、勢いでbookmarkletをつくってみました。実行すると、見ているページのtitleをプロンプト表示します。文字列が選択された状態で表示されるので、「ctrl+C」すればすぐにコピペできます。

 

■見ているページのtitleをプロンプト表示

見ているページのtitleを表示

 

 

ついでにこれも。titleだけではなくて<a>タグごと吐き出すもの。target=_"blank"つきです。

■見ているページへの<a>タグをプロンプト表示

見ているページへのリンクタグを表示

 

探せば似たものがたくさんあると思いますが、、、ブラウザの「お気に入り」に入れて、ご自由におつかいください。

 

2006年8月20日

PHPカンファレンス2006に行ってきました。

昨日は、蒲田の大田区産業プラザで開催されたPHPカンファレンス2006に行ってきました。

今年で7回目とのこと。自分は初参加。
業界関係者(っていうのかな)が一堂に集結してて、集まった顔ぶれを見てるだけで十分おなかイッパイな感。

 

個人的には、聞きたかったフレームワークについての話がいろいろ聞けました。2年前はメジャーだったMojaviが、いまはすでに遺物扱いされているってことがいちばん印象的でした。じゃあいまから2年後、いまあるフレームワークたちはどーいう存在になっているんでしょ?移り変わり早いなあ。

あ、ちなみにnewsingEthnaフレームワークを使っています。

 

あと、MagpieRSSのよみかたをずっと「まぐぴー」だと思ってました。「まぐぱい」なんですね、ハイ。

 

2006年8月 8日

phpでheaderが出力できなくてハマった件

<?php
header("Content-Type: text/xml; charset=utf-8");
?>

なぁんて単純なコードをつくって、ブラウザアクセスすると

Warning: Cannot modify header information - headers already sent by (output started at hoge.php:1) in hoge.php on line 2

と怒られる現象に悩まされること1昼夜。
 
なんで1行目でheaders already sentなんて言われるねん? とhttpヘッダを確認してみたり ob_flash() を試してみたりとハマりまくった末。普段愛用しているテキストエディタNoEditorで、ファイル保存するときに文字コードを「Unicode (UTF-8 BOM有)」形式で保存してたのが原因でした。
 
ファイル先頭に不可視のBOMコードがついてた訳です。そのコードが、phpでhttpヘッダ制御をする前に送信されちゃってたのが原因ぽいですね。orz。分かってしまえばなんてことないじゃーん。


about

平島浩一郎
株式会社マイネット・ジャパン



katy(ケイティ) - 携帯サイト作成無料CMS
newsing(ニューシング)
終電jp
まとめてブログ検索
あわせて読みたい

Powered by Movable Type
株式会社マイネット・ジャパン