每个文件中都有很多代码,要发布的代码太多了,因此,我为您提供了每个文件中发生情况的大致信息。
index.php [html下拉菜单代码等]
scripts.js [AJAX从下拉列表中检测到用户选择,抓取了fetch.php,后者将数据库拉出以生成用于辅助下拉列表选择的html代码,并将其放入index.php中]
fetch.php [根据用户选择和数据库查询生成辅助下拉代码]
我需要查看确切要调试的内容,所以我想回显sql select语句:
$query = "SELECT * FROM databasename WHERE.."
当用户从fetch.php
中进行选择时,它位于index.php
中-我该怎么做?
答案 0 :(得分:5)
当我处理AJAX时,我以JSON返回,我使用的一个技巧是利用输出缓冲。您不能只回显或输出所需的任何内容,因为它会弄乱JSON数据,因此举个例子,
ob_start(); //turn on buffering at beginning of script.
.... other code ...
print_r($somevar);
.... other code ...
$debug = ob_get_clean(); //put output in a var
$data['debug'] = $debug;
header('Content-Type: application/json');
echo json_encode($data); //echo JSON data.
这是将脚本的所有输出包装到JSON数据中,以免格式混乱。
然后在javascript端,您可以使用console.log
$.post(url, input, function(data){
if(data.debug) console.log(data.debug);
});
如果您不习惯使用console.log()
进行调试,通常可以点击F12
并在大多数浏览器中打开调试器。然后在那里,输出将被发送到“控制台”。我记得IE9与console.log()
有点问题,但我不想走得太远。
注意:,只需确保在将其移至生产环境时不要在代码中保留这些内容,只需将这一行注释掉就非常简单,
//$data['debug'] = $debug;
然后您的调试信息将不会在生产中公开。还有其他自动执行此操作的方法,但这取决于您是否进行本地开发然后发布到服务器。例如,您可以在$_SERVER['SERVER_ADDR'];
或本地::1
上的127.0.0.1
上切换它。这有一些缺点,主要是无法从命令行界面(CLI)获得服务器地址。因此,通常我会将其绑定到一个全局常量中,该常量说明网站处于哪种“模式”(包括在公共入口点中,通常是index.php中)。
if(!defined('ENV_DEVELOPMENT')) define('ENV_DEVELOPMENT','DEVELOPMENT');
if(!defined('ENV_PRODUCTION')) define('ENV_PRODUCTION','PRODUCTION');
if(!defined('ENVIRONMENT')) define('ENVIRONMENT',ENV_DEVELOPMENT);
//site is in Development mode, uncomment for production
//if(!defined('ENVIRONMENT')) define('ENVIRONMENT',ENV_DEVELOPMENT);
然后检查它很简单:
if(ENVIRONMENT == ENV_PRODUCTION ) $data['debug'] = $debug;
如果您知道如何使用错误报告,甚至可以使用
if(ini_get('display_errors') == 1) $data['debug'] = $debug;
仅在显示错误打开时才会显示调试。
希望有帮助。
更新
因为我在评论中提到了它,所以下面是将它包装在一个类中的示例(这是简化版本,因此我没有对其进行测试)
class LibAjax{
public static function respond($callback, $options=0, $depth=32){
$result = ['userdata' => [
'debug' => false,
'error' => false
]];
ob_start();
try{
if(!is_callable($callback)){
//I have better exception in mine, this is just more portable
throw new Exception('Callback is not callable');
}
$callback($result);
}catch(\Exception $e){
//example 'Exception[code:401]'
$result['userdata']['error'] = get_class($e).'[code:'.$e->getCode().']';
//if(ENVIRONMENT == ENV_DEVELOPMENT){
//prevents leaking data in production
$result['userdata']['error'] .= ' '.$e->getMessage();
$result['userdata']['error'] .= PHP_EOL.$e->getTraceAsString();
//}
}
$debug = '';
for($i=0; $i < ob_get_level(); $i++){
//clear any nested output buffers
$debug .= ob_get_clean();
}
//if(ENVIRONMENT == ENV_DEVELPMENT){
//prevents leaking data in production
$result['userdata']['debug'] = $debug;
//}
header('Content-Type: application/json');
echo self::jsonEncode($result, $options, $depth);
}
public static function jsonEncode($result, $options=0, $depth=32){
$json = json_encode($result, $options, $depth);
if(JSON_ERROR_NONE !== json_last_error()){
//debug is not passed in this case, because you cannot be sure that, that was not what caused the error. Such as non-valid UTF-8 in the debug string, depth limit, etc...
$json = json_encode(['userdata' => [
'debug' => false,
'error' => json_last_error_msg()
]],$options);
}
return $json;
}
}
然后,当您做出AJAX响应时,只需像这样包装它(注意$ result是通过引用传递的,这样我们就不必做返回,并且在例外情况下,我们将$ result更新为“ real时间”,而不是完成时间
LibAjax::respond( function(&$result){
$result['data'] = 'foo';
});
如果您需要将其他数据传递到闭包中,请不要忘记可以像这样使用use
语句。
$otherdata = 'bar';
LibAjax::respond( function(&$result) use($otherdata){
$result['data'][] = 'foo';
$result['data'][] = $otherdata;
});
如果环境正确(已注释掉),则此方法可捕获所有输出并将其置于调试状态。请请确保实施某种保护,以使输出内容不会在生产时发送给客户,我不能强调太多。它还捕获任何将其放入错误的异常。并且还处理标头和编码。
此功能的一大好处是JSON的结构一致,您将知道(在客户端)如果if(data.userdata.error)
,则在后端有一个异常。它为您提供了一个调整标头,JSON编码等的地方...
PHP7中的一个注释,您必须或应该添加Throwable接口(而不是Exception)。如果要捕获Error和Exception类,或者执行两个catch块。
让我们说我做了很多AJAX并一直讨厌重写它,我的实际课程比这还要广泛,但这就是要点。
干杯。
UPDATE1
要显示的内容,我要做的一件事是在console.log()之前解析数据变量
这通常是因为您没有将正确的标头传递回浏览器。如果发送(在调用json_encode之前)
header('Content-Type: application/json');
这只是让浏览器知道它返回的数据类型。大多数人忘记的一件事是,在网络上所有回复都是以文本形式完成的。甚至图像或文件下载以及网页。都是文本,使文本变得特别的是浏览器认为的Content-Type
。
关于header
的一件事要注意,您不能在发送标题之前输出任何内容。但是,这与我发布的代码配合得很好,因为该代码将捕获所有输出,并在发送标头后将其发送。
我将原始代码更新为具有标头,我将其保存在稍后发布的更复杂的类中。但是,如果在其中添加它,则无需手动解析JSON。
我要提到的最后一件事是检查是否返回了JSON或文本,如果在开始输出缓冲之前发生一些错误,您仍然可以获取文本。
有两种方法可以做到这一点。
如果Data是需要解析的字符串
$.post(url, {}, function(data){
if( typeof data == 'string'){
try{
data = $.parseJSON(data);
}catch(err){
data = {userdata : {error : data}};
}
}
if(data.userdata){
if( data.userdata.error){
//...etc.
}
}
//....
}
或者,如果您具有标题及其始终为JSON的标题,那么它会更简单
$.post(url, {}, function(data){
if( typeof data == 'string'){
data = {userdata : {error : data}};
}
if(data.userdata){
if( data.userdata.error){
//...etc.
}
}
//....
}
希望有帮助!
UPDATE2
因为这个话题很多,所以我在GitHub上放置了上述代码的修改版本,您可以在这里找到它。
https://github.com/ArtisticPhoenix/MISC/blob/master/AjaxWrapper/AjaxWrapper.php
答案 1 :(得分:0)
回显内容并执行die()或退出;然后...,然后在浏览器的“网络”选项卡中,开始记录,运行Ajax请求(它将失败),但检查资源/名称,然后查看“响应”,它将向您显示回显了什么在脚本中
来自:Request Monitoring in Chrome
Chrome当前内置了一个解决方案。
使用CTRL + SHIFT + I(或导航到“当前页面控件”>“开发人员”>“开发人员工具”。
在较新版本的Chrome中,点击扳手图标>工具>开发人员工具。)以启用开发人员工具。
在开发人员工具中,单击“网络”按钮。如果尚未启用,请在会话中启用它,或者始终启用它。
点击“ XHR”子按钮。
发起AJAX调用。
您将在“资源”下方的左栏中看到项目。
单击资源,有两个选项卡显示标题和返回内容。
其他浏览器也具有“网络”选项卡,但是您需要使用我的注释来获取查询的字符串值。
上面的ArtisticPhoenix解决方案很令人愉快。