很多时候我们都要纠结于代码开发过程中的数据 dump 工作,诸如 接口测试,程序调错,不得不在代码行中加入各种 echo,dump,exit 等等操作,每次我们都需要在代码里面不停的加,然后调试完了再去删,下次有问题,还是这么琐碎的去做,是不是很麻烦,为此 终于下定决心来实现一个不再需要这么蛋比的工具了.
实现思路很简单,使用 url 参数控制是否启用内容打印服务,根据标签过滤打印的内容,让不同的开发者可以独立进行内容测试.
分成2组文件
1. 后端文件
<?php
/**
* 数据调试 操作类
*
* 使用简单的方式来打印脚本运行过程中的请求过程
*
* @author vb2005xu@qq.com
*/
class AsDebug
{
private $disable = true;
private function __construct()
{
$this->url = Request::fullUrl();
if ( function_exists('getallheaders') )
{
$this->headers['request'] = getallheaders();
}
else
{
$this->headers['request'] = self::emu_getallheaders();
}
$this->headers['response'] = headers_list();
$this->cookies = isset($_COOKIE) ? $_COOKIE : array();
$this->sessions = isset($_SESSION) ? $_SESSION : array();
$this->servers = isset($_SERVER) ? $_SERVER : array();
$this->items = [];
$disable = Input::get('asdebug');
if ( $disable == ' vb2005xu@qq.com' )
{
$this->disable = false;
}
$this->tag = Input::get('asdebug-tag','');
$path = storage_path() . '/asdebug';
if ( !is_dir($path) ){
mkdir($path, 0700, true);
}
$this->filename = $path . '/log-' . md5($this->tag) . '.txt';
}
function __destruct()
{
// 进行资源释放
if ( $this->disable ) return;
$data = array(
'url' => $this->url,
'headers' => $this->headers,
'cookies' => $this->cookies,
'sessions' => $this->sessions,
// 'servers' => $this->servers,
'items' => $this->items,
'cretae_at' => time(),
);
$id = md5( $data['url'] . $data['cretae_at'] );
$data = json_encode( array(
'id' => $id,
'tag' => $this->tag,
'content' => $this->output($data)
) );
file_put_contents($this->filename, $data);
}
private static function emu_getallheaders()
{
foreach ($_SERVER as $name => $value)
{
if (substr($name, 0, 5) == 'HTTP_')
{
$name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))));
$headers[$name] = $value;
} else if ($name == "CONTENT_TYPE") {
$headers["Content-Type"] = $value;
} else if ($name == "CONTENT_LENGTH") {
$headers["Content-Length"] = $value;
}
}
return $headers;
}
public static function instance()
{
static $self = null;
if ( is_null($self) ) $self = new self;
return $self;
}
public function getContent()
{
if ( is_readable($this->filename) )
{
$json = file_get_contents($this->filename);
if ( !empty($json) )
{
$data = json_decode($json, true);
if ( $data['tag'] == $this->tag)
{
return $json;
}
}
}
return '{}';
}
public function isEnable()
{
return !$this->disable;
}
public function getTag()
{
return $this->tag;
}
public function disable($disable=false)
{
$this->disable = $disable;
}
private function write($vars, $label = '')
{
if ( $this->disable ) return;
$this->items[] = array(
'label' => $label,
'vars' => $vars,
);
}
private function output($vars, $label = '')
{
$content = "<pre>\n";
if ($label != '')
{
$content .= "<strong>{$label} :</strong>\n";
}
$content .= htmlspecialchars(print_r($vars, true), ENT_COMPAT | ENT_IGNORE);
$content .= "\n</pre>\n";
return $content;
}
public static function dd($vars, $label = '')
{
self::instance()->write($vars, $label);
}
public static function ddexit($vars, $label = '')
{
self::instance()->write($vars, $label);
exit;
}
public static function view()
{
self::instance()->disable(true);
return self::instance()->getContent();
}
}
在某个控制器中加入一个action
public function asdebug()
{
$f = Input::get('f');
if ( $f == 'json' )
{
return AsDebug::view();
}
return $this->view('asdebug');
}
做一个简单的视图文件
<?php
$this->extend('_layouts/master');
?>
<?php $this->block('js-after');?>
<script>
var ids = {};
var calc_num = 0;
function setContent(json)
{
if ( !json.id ) return;
var id = json.id;
if ( ids[ id ] ) return;
ids[ id ] = 1;
calc_num ++;
$('#v-asdebug').prepend('<p> 编号: ' + calc_num + '<br>' + json.content + '</p><hr>');
if ( calc_num == 500 )
{
calc_num = 0;ids = {};
}
}
function refresh()
{
$.getJSON( '<?php echo URL::route('asdebug')?>',
{f: 'json', 'asdebug-tag': '<?php echo Input::get("asdebug-tag")?>'},
function(json){
setContent(json);
setTimeout('refresh()',3000);
} );
}
refresh();
</script>
<?php $this->endblock();?>
<?php $this->block('content');?>
<div>
<div class="main-content-title">
<div class="float-left">
<h2 class="">asdebug 调试工具</h2>
</div>
</div>
<div class="main-content-body" id="v-asdebug">
</div>
</div>
<?php $this->endblock();?>
在全局视图文件中加入,实现页面中异步的ajax请求也能自动使用 asdebug 功能进行数据记录:
<?php if ( AsDebug::instance()->isEnable() ):?>
<script type="text/javascript">
$.ajaxSetup({data: {
'asdebug': '<?php echo Input::get("asdebug")?>',
'asdebug-tag': '<?php echo Input::get("asdebug-tag");?>'
}});
$(document).ready(function(){
var ss = 'asdebug=<?php echo Input::get("asdebug")?>&asdebug-tag=<?php echo Input::get("asdebug-tag");?>';
$('a').each(function(){
var url = $(this).attr('href');
if ( '' != url )
{
var pieces = url.split("?");
url = pieces[0] + '?' + ss;
if ( pieces.length > 1 )
{
url += '&' + pieces[1];
}
$(this).attr('href', url);
}
});
});
</script>
<?php endif;?>
此处代码中可能包含部分 laravel 的代码,但是很容易移植到其它的框架中,希望对大家有所帮助.
此工具解决了 线上,线下代码 dump的问题
此处简单修正下 定时器的小问题,当网络请求失败后,会停止,此处解决此小问题
<script src="//cdn.bootcss.com/jquery/1.11.2/jquery.js"></script>
<script>
var ids = {};
var calc_num = 0;
var ii = 0;
function setContent(json)
{
console.log(++ii);
if ( !json.id ) return;
var id = json.id;
if ( ids[ id ] ) return;
ids[ id ] = 1;
calc_num ++;
$('#v-asdebug').prepend('<p>[' + calc_num + '] ' + json.create_at +'<br>' + json.content + '</p><hr>');
if ( calc_num == 500 )
{
calc_num = 0;ids = {};
}
}
function refresh()
{
$.ajax('http://dev.duixueren.net/asdebug.html',{
type: 'GET',
dataType: 'json',
data: {f: 'json', 'asdebug-tag': '123'},
async: false,
cache: false,
error: function (xhr, status, et) {
console.warn(status, et);
},
complete: function (xhr, status, et) {
setTimeout('refresh()',500);
},
success: function(json, status, xhr){
setContent(json);
}
});
}
$(document).ready(function(){
refresh();
});
</script>
<div>
<div class="main-content-title">
<div class="float-left">
<h2 class="">asdebug 调试工具</h2>
</div>
</div>
<div class="main-content-body" id="v-asdebug">
</div>
</div>