2014年3月5日水曜日

リワード広告の仕組み(2)

さて、いよいよ実際にリワードシステムを作ります。

とは言ったものの、セッションやクッキーに対する理解が浅かったので勉強し直してきました。詳しくはGoogle先生が教えてくれるでしょうから簡単に説明します。

クッキーとは、ブラウザ側にデータを保存するものです。一度ログインしたHPに二度目にアクセスするとIDやパスワードが保存されてますね、あれがクッキーです。語源はそのまんまお菓子のクッキーらしいのでブラウザにクッキーを食べさせる、というイメージなのでしょうか。もぐもぐ。
反対に、セッションはサーバー側に保存するデータになります。ブラウザ側はそのセッションIDのみをクッキーに保存しておきます。サイトにアクセスすると、ブラウザに保存されているセッションIDからサーバーに保存されているデータを呼び出します。


ではコードを交えて解説を。
セッションはsession_start()で開始されます。セッションがまだ開始されていない状態でこの関数が呼び出されるとセッションIDが生成されます。すでにセッションが開いている時にこの関数が呼ばれると、前のセッションが呼び出されるようです。
<?php
  session_start();
?>
セッションIDはブラウザにクッキー名PHPSESSIDで保存されます。セッション変数は$_SESSION[変数名]で管理されています。セッションIDを確認するのであれば
  session_start();
  print($_SESSION[PHPSESSID]);
で見ることができます。ページへの訪問回数を数えるのであれば
  session_start();
  if(isset($_SESSION["visited"])){
 $_SESSION["visited"]++;
 print($_SESSION["visited"]."回目の読み込みです");
  }else{
 $_SESSION["visited"] = 0;
 print("初めての読み込みです");
  }
とすればセッションID訪問回数をカウントすることができます。セッションIDを持つクッキーは基本ブラウザが閉じられると破棄されるのですが、クッキーの生存時間を任意に指定することもできます。

基本はこれを利用してできそうです。全部書くとキリがないのもあるので僕が詰まったとこや要点だけ。

まず、GooglePlayへの遷移ですが、リンク先を
https://play.google.com/store/apps/details?id=com.android.chrome
としてしまうとGooglePlayへのアクセス方法をユーザが選べてしまいます。ブラウザを起動するのかGooglePlayのアプリを起動するのかユーザが選べてしまいます。そこまで困りはしないのですが、できれば強制的にGooglePlayアプリへ遷移させたい。
なので、リンク先は
market://details?id=com.android.chrome
としてあげれば問答無用でGooglePlayのアプリがAndroid端末で起動します。もちろんこれはPCブラウザでは反応しません。


それと、サーバー側でのセッションIDの保存方法。僕はここでかなり躓きましたし実際今も完璧に理解できていない気がします。セッションIDはサーバー側で保持するものですが、その保存方法がいくつかあるようです。
これらはphp.iniのsession.save_handlerで設定できます。また保存場所はsession.save_pathに絶対パスを指定することで変更できます。
しかし、共用サーバーなどの場合サーバー全体で設定が変わってしまうため作業フォルダに.htaccessファイルを作成しました。ここに設定を記述することで.htaccessを置いたフォルダ以下のPHPプログラムにその設定が反映されます。

保存方法そのいち
memcached(メモキャッシュディーと読む?)を利用する方法。使ってるサーバーのphp.iniの設定がこれになっていたのですが、memcachedというキャッシュシステムを使ってサーバーに値を保存する方法。
.htaccessで
php_value session.save_handler = memcache
php_value session.save_path = "tcp://host:11211"
と記述することで保存形式をmemcachedにできます。

保存方法そのに
ファイルで保存する方法。session.save_handlerの値をfilesにすることで設定可能です。
php_value session.save_handler = files
php_value session.save_path = "フォルダの絶対パス"

そのさん
データベースを使う方法
データベースに値を保存する方法です。セッションデータの共有などを行うのであればこの方法が便利。session.save_handlerの値をuserにします。session.save_pathは指定しません。
php_value session.save_handler = users

ちなみに、躓いた経緯はこんな感じ。

最初memcacheで深く考えずにセッション関係の関数を使用していたのですが、最初何回かはうまくいくのに途中からセッションが保持されなくなってしまった。memcachedの存在も調べて初めて知ったのでよくわからない。。。
じゃあファイルで保存できるらしいしそうしよう。
そんな気持ちで設定を変え、保存するフォルダパスを指定しました。
実行テスト
一回目

 いい感じ。ちゃんとセッションIDが発行されています。
更新ボタンを押すと、二回目って出るはず。
二回目
アイエエエエエエエ!?ショカイ!?ショカイナンデエエ!?
更新されません。もいっかい押したら
あれ、更新される。。。。

その後も何回か試してみましたが、必ず二回更新しないとセッションの値が更新されないことに。

ログを見てもなにも出てなかったのですが、ひたすらネットで情報を漁っているといくつか似たような事例が。間違っているかもしれませんが、ファイルシステムがロックされていることが関係している模様。一度アクセスすると30秒ほどはファイルにアクセスできないみたい。

実際30秒間隔を空けてあげるときちんと更新されました。しかこんな自由意思に頼ったシステムで納品するわけにもいかず、先ほど調べているうちに知ったDBを使ったセッションの管理を試してみることに。

これには、あらかじめセッション保存用のテーブルを用意してあげて
session_set_save_handler("open","close","read","write","destroy",gc");
としてセッションの保存に関連するメソッド(open(),close(),read(),write(),destroy(),gc())を定めてあげればいいだけです。僕はsession_hanlder.phpという形で一つのファイルにしてしまったのですがだいたいこんな感じになります。
<?php
        //データベース情報
 $dsn='mysql:dbname=xxx;host=xxx.xxx.xxx.xxx';
        $user='user';
        $password='password';


    //データベースへ接続
 function connect_db(){
 global $dsn,$user,$password;
  try{
   $dbh = new PDO($dsn,$user,$password);
   //print('接続に成功しました
');
  }catch(PDOException $e){
   //print('Error:'.$e->getMessage());
  }
  return $dbh;
 }

 function open(){
  //データベース接続

                return true;
 }
 
 function close(){
  return true;
 }

 function read($id){
  //データベース読み込み
 
  return $data;
 } 
 
 function write($id,$data){
  //データベースへの書き込み・あるいは更新
 }

 function destroy($id){
  //データベースからデータを削除
 }

 function gc($maxlifetime){
  //ガーベッジコレクションの処理
 }

 session_set_save_handler("open","close","read","write","destroy","gc");
  
?>

これでようやく問題なくセッションの管理ができるようになりました。そんなに難しいことじゃないんだけど、苦労した。。。

学んだこととしては


  • アプリDLなどを跨いでのユーザの認証にセッションを使うこと
  • セッションファイルはmemcached,ファイル,DBなどで管理ができること

の二点が大きかったです。あとはセキュリティとか、めんどくさry...いろいろですね。なんとかなって良かったです。

0 件のコメント:

コメントを投稿