cakePHPのTest時にEXPLAINの結果を表示する

August 10, 2011,
tags: cakephp php


このエントリーをはてなブックマークに追加

cakephp1.3でUnitTestを書く際は、Simpletestを使っていると思います。(1.x系)
DebugKitとか使えばExplainの結果がみれるし、いらないと言われればいらないのですが、UnitTestの時にExplainも表示させたいとか、DebugKitが使えない状況って意外とあったりします。JSON返すだけの処理しかなかったりとか。。。

んで、やっぱExplainてきなのをSimpletestとかで見れるようにしようとおもいElementを改造することにしました。
まずは「cake/lib/element/sql_dump.php」を「app/view/element/sql_dump.php」にコピーします。
んであとは中にをごっそり書き換えるだけ。
以下のように書き換えれば実行結果がみれるようになります。

if (!class_exists('ConnectionManager') || Configure::read('debug') < 2) {
	return false;
}

//
$exQuery = array();

$noLogs = !isset($logs);
if ($noLogs):
	$sources = ConnectionManager::sourceList();

	$logs = array();
	foreach ($sources as $source):
		$db =& ConnectionManager::getDataSource($source);
		if (!$db->isInterfaceSupported('getLog')):
			continue;
		endif;
		$logs[$source] = $db->getLog();
	endforeach;
endif;
if ($noLogs || isset($_forced_from_dbo_)):
	foreach ($logs as $source => $logInfo):
		$text = $logInfo['count'] > 1 ? 'queries' : 'query';
		printf(
			'<table class="cake-sql-log" id="cakeSqlLog_%s" summary="Cake SQL Log" cellspacing="0" border = "0">',
			preg_replace('/[^A-Za-z0-9_]/', '_', uniqid(time(), true))
		);
		printf('<caption>(%s) %s %s took %s ms</caption>', $source, $logInfo['count'], $text, $logInfo['time']);
	?>
	<thead>
		<tr><th>Nr</th><th>Query</th><th>Error</th><th>Affected</th><th>Num. rows</th><th>Took (ms)</th></tr>
	</thead>
	<tbody>
	<?php
		foreach ($logInfo['log'] as $k => $i) :
			if ( strpos( $i['query'], 'SELECT') !== false ) {
				$exQuery[$k] = $i['query'];

			}
			echo "<tr><td>" . ($k + 12) . "</td><td>" . h($i['query']) . "</td><td>{$i['error']}</td><td style = \"text-align: right\">{$i['affected']}</td><td style = \"text-align: right\">{$i['numRows']}</td><td style = \"text-align: right\">{$i['took']}</td></tr>\n";
		endforeach;
	?>
	</tbody></table>
	<?php
	endforeach;
else:
	echo '<p>Encountered unexpected $logs cannot generate SQL log</p>';
endif;
// EXPLAIN用の拡張
$exResult = array();
foreach($exQuery as $key => $value ) {
	$exTmp = $db->query('EXPLAIN '.$value);
	$exResult[] = array('query' => 'EXPLAIN ' .$value, 'result' => $exTmp[0][0] );
}
?>
<?php if ( !empty($exResult) ) :?>
<br />
<br />
<div style="text-align:center">EXPLAIN info</div>
	<?php foreach( $exResult as $exKey => $exValue) :  ?>
	<table class="cake-sql-log" cellspacing="0" border = "0">

	<thead>
		<tr><th style="width:100px;">select_type</th><th style="width:100px;">table</th><th style="width:80px;">type</th><th>possible_keys</th><th>key</th><th>key_len</th><th>ref</th><th>rows</th><th>Extra</th></tr>
	</thead>
	<tbody>
	<tr style="color:#FF0000;">
	<?php foreach( $exValue['result'] as $exIdx => $ex ) : ?>
	<?php if ( $exIdx != 'id') :?>
	<td>
	<?php echo $ex;?>
	</td>
	<?php endif;?>
	<?php endforeach;?>
	</tr>
	<tr>
	</tr>
	<tr >
	<td colspan="9" style="background-color:#ccc;font-size:8px;">
	Query: <?php echo $exValue['query'];?>
	</td>
	</tr>
	</tbody>
	</table>

	<?php endforeach;?>

<?php endif;?>

ちょっとしたときに意外と便利だったりしますよー。

comments powered by Disqus