[Research Artisan]のソースコード解析メモ2

ResearchArtisanLiteの解析メモその2
その1はこちら:Research Artisan Liteのソースコード解析メモ

エントリポイントであるindex.phpから、データの取得周りまでの処理の流れを調べたときのメモです。
プログラムのソースを改変する人向けなので、1ユーザとして使用する際には全く必要ない情報です。




ヘルパーのロードは,RaView->showView()内からコールされる_loadHelper()で行われる.
このメソッドへ到達するための流れは以下の通り。

index.php
    Ra->execute()
        Ra->_showView()
            RaView->showView()  
                RaView->_loadHelper()
                    RaView->_checkHelper()
                        $helperFile = RA_CORE_DIR. RA_HELPER_DIR. ucfirst($controller). 'Helper.php';
                        require $helperFile;
 
                    return new $helperName($request, $session, $message, $result, $controller, $action);



Helperクラスをnewするには、コンストラクタで以下のパラメータが必要

public function __construct(
                            RaRequest $request,
                            RaSession $session, 
                            RaMessage $message,
                            RaResult $result=null
                            $controller,
                            $action );



コンストラクタ引数は、ResearchHelperクラスを見るとresultについては省略可能となっている

class ResearchHelper extends BaseHelper {
      public function __construct(RaRequest $request, RaSession $session, RaMessage $message, RaResult $result=null, $controller, $action) {
        parent::__construct($request, $session, $message, $result, $controller, $action);
      }




コンストラクタ引数はそれぞれ、下記のメソッドで初期化されている。

Ra->__construct()
    $_request    = new RaRequest();
    $_session    = new RaSession();
    $_message    = new RaMessage();
    $_controller = $this->_request->get('controller');
    $_action     = $this->_request->get('action');
 
Ra->execute()
    $result = new RaResult();





ページ(view)に表示するデータは、ResearchHelper->uniqueCount()等で取得しているが、これはコンストラクタで渡されたresultの情報を返しているだけ

public function uniqueCount() {
    print $this->getFormatNumber($this->result->get('uniqueCount'));
}



resultへの値をセットは、ReserchController->_doResearch()で行われている。
具体的にはfindSummary()メソッドの戻り値。

_doResearch() {
    $log = new Log();
    ...
    $results = $log->findSummary($findOptions, $method, $yyyyMmOptions, $compareValue);
    ...
 
    $result = $this->result;
    foreach($results as $k => $v) {
      $result->set($k, $v);
    }
    ...
}




Log->findSummary()では、findQuery()でDBからの結果セットを取得している。

$rs = $this->findQuery($options);
while ($row = $this->fetchRow($rs)) {
  $this->clearData();
  $data = $this->getData();
 
  foreach($data as $column => $value) {
    if (isset($row[$column])) $this->setValue($column, $row[$column]);
  }
 
  $this->setValue('yyyy', $term['yyyy']);
  $this->setValue('mm', $term['mm']);
  $function = '_'. $method;
  if (method_exists($this, $function)) {
    $this->$function();
  }
}




fetchRow()は継承元のRaModel.phpで定義され、MySQLのAPIをコールしている。
スコープがprotectedなので、継承先クラスしか本メソッドはコールできない。

protected final function fetchRow($rs) {
    return mysql_fetch_array($rs, MYSQL_ASSOC);
}



findQuery()も、RaModelで定義されている。

protected final function findQuery($options=null) {
    $query = 'SELECT *';
    $query .= ' FROM ' . $this->_escapeName($this->_table);
    $query .= $this->_makeOption($options);
    return $this->query($query);
}




findQueryへ渡す引数と、戻ってくるSQLの例は以下のような感じになっている

引数($options)
    array(2) {
      ["condition"]=>
      array(3) {
        [0]=>
        string(19) "dd >= ? AND dd <= ?"
        [1]=>
        string(2) "25"
        [2]=>
        string(2) "25"
      }
      ["order"]=>
      string(30) "dd ASC, hh ASC, mi ASC, ss ASC"
    }
 
戻り値
    "SELECT * FROM `ra_log_201205` WHERE dd >= '25' AND dd <= '25' ORDER BY dd ASC, hh ASC, mi ASC, ss ASC"




また、findQueryの呼び出し元だったfindSummaryの引数例は、以下の通り

options
    array(2) {
      ["condition"]=>
      array(1) {
        [0]=>
        string(0) ""
      }
      ["order"]=>
      string(30) "dd ASC, hh ASC, mi ASC, ss ASC"
    }
 
method
    string(4) "time"
 
yyyyMmOptions
    array(6) {
      ["yyyyFrom"]=>
      string(4) "2012"
      ["mmFrom"]=>
      string(2) "05"
      ["ddFrom"]=>
      string(2) "25"
      ["yyyyTo"]=>
      string(4) "2012"
      ["mmTo"]=>
      string(2) "05"
      ["ddTo"]=>
      string(2) "25"
    }
 
compareValue
    NULL




Logクラスの継承関係は以下の通り

class Log extends RaModel {
    public function __construct($noCreate=false, $yyyymm=null) {
        ...
    }
    ...
}
 
abstract class RaModel {
    protected final function findQuery($options=null) {
        ...
    }
 
    ...
}





調査結果より,通常の流れ以外でDBからデータ取得したい時は…
何らかの処理で、特別にアクセスログのデータが欲しい場合は、自前でLogクラスをnewしてデータを取得する。既存の処理を流用する時は、findSummaryメソッドの第二引数で、欲しいデータが表示されている画面を指定すると楽チン。その際,検索条件として、findOptionsを渡さなければならないが、何を渡すかはfindSummary()の内部でデバッグログを落とすように変更し、結果から逆算した方が手っ取り早い。


上記方針に従って試した結果。
例えば以下のコードで、特定の日に対するアクセス数が取得可能となる。

    $request    = new RaRequest();
    $session    = new RaSession();
    $message    = new RaMessage();
    $controller = "";
    $action     = "";
    $result     = new RaResult();
 
 
 
    $findOptions = array();
    $findOptions["condition"] = array();
    $findOptions["condition"][] = "";
    $findOptions["condition"][] = "dd ASC, hh ASC, mi ASC, ss ASC";
 
    $yyyyMmOptions = array();
    $yyyyMmOptions["yyyyFrom"] = "2012";
    $yyyyMmOptions["mmFrom"]   = "05";
    $yyyyMmOptions["ddFrom"]   = "27";
    $yyyyMmOptions["yyyyTo"]   = "2012";
    $yyyyMmOptions["mmTo"]     = "05";
    $yyyyMmOptions["ddTo"]     = "27";
 
    $compareValue = NULL;
 
    $log = new Log(true);
    $log->setKeys();
    $results = $log->findSummary($findOptions, "time", $yyyyMmOptions, $compareValue);
    echo( "UU=" . $results["uniqueCount"] . "\n" );
    echo( "PV=" . $results["totalCount" ] . "\n" );

関連記事

コメントを残す

メールアドレスが公開されることはありません。