很多时候我们都要纠结于代码开发过程中的数据 dump 工作,诸如 接口测试,程序调错,不得不在代码行中加入各种 echo,dump,exit 等等操作,每次我们都需要在代码里面不停的加,然后调试完了再去删,下次有问题,还是这么琐碎的去做,是不是很麻烦,为此 终于下定决心来实现一个不再需要这么蛋比的工具了.
实现思路很简单,使用 url 参数控制是否启用内容打印服务,根据标签过滤打印的内容,让不同的开发者可以独立进行内容测试.
分成2组文件
1. 后端文件
<?php /** * 数据调试 操作类 * * 使用简单的方式来打印脚本运行过程中的请求过程 * * @author [email protected] */ 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 == ' [email protected]' ) { $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>