I have a script with alot of nested includes and functions calling each other from lots of if conditions. Basically, its a coding nightmare.
Is there any way i can "PRINT" the PHP code executed ? I mean, print the actual flow of the code and the path taken by the script from start to end ?
PHP can't do this out of the box. You'd need to install the xDebug extension on your PHP development machine. Once installed, you could use the code coverage function to determine which lines have executed.
Lacking that, I'd create a simple debug function to include at the top of your code
public function myDebugString($string)
{
file_put_contents('/tmp/debug.log',"$string\n",FILE_APPEND);
return;
}
and then add calls to this throughout you code
myDebugString('Called at ' . __LINE__);
And then tail the log file created. Removing the debug statements is a simple find/replace operation for your editor once you're done.
Many frameworks have debugging objects that do way more than this built it, but if you're dealing with stand alone code something simple like this should be enough to get you by.
You can try debug_backtrace() or debug_print_backtrace().
Additionally, I recommend using Xdebug. It prints a very useful stack trace on exceptions (you can configure it to print out every method parameter and every local variable (xdebug.collect_params=4 and xdebug.show_local_vars=on configuration parameters).
Take a look at code coverage tools. This allows you to identify those functions and lines of code that are actually executed when a script runs
Related
I'd like to debug some PHP code, but I guess printing a log to screen or file is fine for me.
How should I print a log in PHP code?
The usual print/printf seems to go to HTML output not the console.
I have Apache server executing the PHP code.
A lesser known trick is that mod_php maps stderr to the Apache log. And, there is a stream for that, so file_put_contents('php://stderr', print_r($foo, TRUE)) will nicely dump the value of $foo into the Apache error log.
error_log(print_r($variable, TRUE));
might be useful
You can use error_log to send to your servers error log file (or an optional other file if you'd like)
If you are on Linux:
file_put_contents('your_log_file', 'your_content');
or
error_log ('your_content', 3, 'your_log_file');
and then in console
tail -f your_log_file
This will show continuously the last line put in the file.
You need to change your frame of mind. You are writing PHP, not whatever else it is that you are used to write. Debugging in PHP is not done in a console environment.
In PHP, you have 3 categories of debugging solutions:
Output to a webpage (see dBug library for a nicer view of things).
Write to a log file
In session debugging with xDebug
Learn to use those instead of trying to make PHP behave like whatever other language you are used to.
Are you debugging on console? There are various options for debugging PHP.
The most common function used for quick & dirty debugging is var_dump.
That being said and out of the way, although var_dump is awesome and a lot of people do everything with just that, there are other tools and techniques that can spice it up a bit.
Things to help out if debugging in a webpage, wrap <pre> </pre> tags around your dump statement to give you proper formatting on arrays and objects.
Ie:
<div> some html code ....
some link to test
</div>
dump $tpl like this:
<pre><?php var_dump($tpl); ?></pre>
And, last but not least make sure if debugging your error handling is set to display errors. Adding this at the top of your script may be needed if you cannot access server configuration to do so.
error_reporting(E_ALL);
ini_set('display_errors', '1');
Good luck!
You can also write to a file like this:
$logFilePath = '../logs/debug.text';
ob_start();
// if you want to concatenate:
if (file_exists($logFilePath)) {
include($logFilePath);
}
// for timestamp
$currentTime = date(DATE_RSS);
// echo log statement(s) here
echo "\n\n$currentTime - [log statement here]";
$logFile = fopen($logFilePath, 'w');
fwrite($logFile, ob_get_contents());
fclose($logFile);
ob_end_flush();
Make sure the proper permissions are set so php can access and write to the file (775).
If you don't want to integrate a framework like Zend, then you can use the trigger_error method to log to the php error log.
Simply way is trigger_error:
trigger_error("My error");
but you can't put arrays or Objects therefore use
var_dump
You can use the php curl module to make calls to http://liveoutput.com/. This works great in an secure, corporate environment where certain restrictions in the php.ini exists that restrict usage of file_put_contents.
This a great tool for debugging & logging php: PHp Debugger & Logger
It works right out of the box with just 3 lines of code.
It can send messages to the js console for ajax debugging and can replace the error handler.
It also dumps information about variables like var_dump() and print_r(), but in a more readable format.
Very nice tool!
I have used many of these, but since I usually need to debug when developing, and since I develop on localhost, I have followed the advice of others and now write to the browser's JavaScript debug console (see http://www.codeforest.net/debugging-php-in-browsers-javascript-console).
That means that I can look at the web page which my PHP is generating in my browser & press F12 to quickly show/hide any debug trace.
Since I am constantly looking at the developer tools for debugger, CSS layout, etc, it makes sense to look at my PHP loggon there.
If anyone does decide to us that code, I made one minor change. After
function debug($name, $var = null, $type = LOG) {
I added
$name = 'PHP: ' . $name;
This is because my server side PHP generates HTML conatining JavaScript & I find it useful to distinguish between output from PHP & JS.
(Note: I am currently updating this to allow me to switch on & off different output types: from PHP, from JS, and database access)
I use cakephp so I use:
$this->log(YOUR_STRING_GOES_HERE, 'debug');
You can use:
<?php
echo '<script>console.log("debug log")</script>';
?>
You can use
<?php
{
AddLog("anypage.php","reason",ERR_ERROR);
}
?>
or if you want to print that statement in an log you can use
AddLog("anypage.php","string: ".$string,ERR_DEBUG_LOW);
I'm calling several functions (which I can't edit) in sequence, but some of the functions redirect the user, so I never get to the next one.
I'm calling a third-party function which has calls to wp_redirect() which I'm able to prevent, but then the next line is exit; which I can't figure out how get around.
I was hoping to get around it with the ob_ functions, but no luck so far.
Any suggestions, hacky or otherwise, will be hugely appreciated!
edit: I have an idea I haven't tried yet - somehow spawning off new processes to perform these tasks - what would be best way to do that, waiting for each to complete before moving on.
I believe is possible to get the source code of the php interpreter ... mess with the exit function and then recompile and install on the web server your new custom version of php ...
I'm afraid you just can't. There is an option to redefind native php function, see runkit_function_redefine.
But in the comments it also says:
language constructs
(eval, die, exit, isset, unset, echo etc.) which might be confused
with functions, cannot be renamed or redefined even with
runkit.internal_override.
You may be able to use runkit_function_redefine. You'll need to make sure you can modify internal functions in your php.ini file in order to be able to change native/internal functions.
I think the php.ini setting you need to ensure is switched on is runkit.internal_override.
I've not tested this.
However, since exit is a language construct I'm not even sure it's possible to get around it even with the above function.
In the end I went with using cURL to make three synchronous requests to a file with different GET params.
Throw an exception in wp_redirect, and wrap the code with try-catch statement, then check if the exception message contains the message you have set and return the response accordingly, I have used this hack with most plugins including woocommerce, ultimatemember etc...
example:
ob_start();
try{
whatever code....
}catch(\Exception $e){
}
echo ob_get_clean();
I modified about 600 lines of code amongst over 5000 lines of code by updating function calls to match the new library I created for use with the script. I have spot some errors manually when updating before by hand, but I believe I overlooked some.
So far, the only way I can spot them is to run the code and have it crash when the error happens. This is a bad idea because such errors will happen before resources are freed.
Here's an example in code that explains my question:
Say I have mainline code (called index.php) that consists of this:
<?php
include "library.php";
$file=fopen("afile","w");
doWrite($file);
brokenFunction();
fclose($file);
exit();
?>
and say library.php contains only this:
<?php
function doWrite($file){
fwrite($file,"Test");
doNothing();
}
?>
Because brokenFunction(); and doNothing(); don't exist, an error is expected. Rather than PHP compile then execute code up until the first failing function call, how do I have PHP check to see if all referenced functions the mainline code links to exist before executing code?
So in my example, I expect an error and the code to stop compiling/executing at $file=fopen("afile","w"); because brokenFunction(); and doNothing(); don't exist.
How do I achieve this?
You can use the built-in function_exists() function:
if (!function_exists('brokenFunction')) {
throw new \Exception('brokenFunction is missing');
}
But this will only raise an error when executing the code.
Some tools like PHPStorm can check your code (without running it) and throw warnings if a function is missing.
Some other tools are listed in this (closed) SO question: Is there a static code analyzer [like Lint] for PHP files?.
The best way I've found to globally debug an environment without using #A.L's method and pasting a function_exists call before every edited line, is to use a PHP debugger of some sort, most likely built into an IDE that compares every function call line against a 'test compile' of your code and all included libraries to make sure the called function exists (and would likely underline it in red if it didn't). A PHP IDE like Aptana might be what you're looking for (especially if you see yourself having future updates to run as this solution will have the time overhead of installing/setting up Aptana).
I'm working on a Laravel application and after some updates I keep getting a comma "," in every http response or console output so I'm crazy trying to find which script file is printing that character.
Is it possible to know which file is writing to the output http response or console?
UPDATE
I've put an echo call in Composer's ClassLoader vendor\composer\ClassLoader.php after an include function for the loaded classes is called, as follows:
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file; echo $file . "\n";
}
And now the comma appears between the following classes are loaded, is this helpful?
C:\Users\Bla\Bla\trunk\vendor/filp/whoops/src/Whoops/Handler/PrettyPageHandler.php
,C:\Users\Bla\Bla\trunk\vendor/laravel/framework/src/Illuminate/Foundation/AliasLoader.php
C:\Users\Bla\Bla\trunk\vendor/laravel/framework/src/Illuminate/Foundation/ProviderRepository.php
UPDATE 2
Found it! As #vladsch said, it was before an opening tag ,<?php in one of my config files, thanks
Since you have it in HTTP and console then this rules out the views.
The culprit is probably a comma inadvertently inserted before the opening <?php tag. Most likely one of the first ones that is at the top of every PHP file.
Do a search for ,<?php or for regex pattern /\s*,\s*<\?php/
Yes, you can, debugging with xdebug or other debbuger tool, step by step (step into) until you find the script.
See this stackover entry for guiadance.
I strongly recommend use a real debug tool as a good pro practice. But maybe for this particular purpouse its a little overwelming.
You can probably narrow it down with some basic debugging. Add a dd('hello') throughout your application.
I would start in the routes.php file. See if the comma appears before or after the hello. If it is before the hello, then the comma is in one of the bootstrapping files.
If the comma is after the hello, then it is most likely in one of your views etc. Keep moving the dd('hello') deeper into your application until it appears.
No you cannot, that's why you should use a version control system (i.e.: git), so you can easily rollback whenever the system breaks.
In your case you could try to search for comma inside every single files of your working directory (escluding vendor and other unimportant folders such as storage)
If you have a debugger you could try to step into to check every single call from the beggining
Is it possible with PHP(5) or other Linux tools on an apache debian webserver to get the file requests a single http request made?
for performance reasons i would like to compare them with the cached "version" of my cake app.
non-cached that might be over 100 in some views.
cached only up to 10 (hopefully).
afaik there are 3 main file functions:
file_get_contents(), file() and the manual fopen() etc
but i cannot override them so i cannot place a logRequest() function in them.
is there any other way? attaching callbacks to functions? intercepting the file requests?
This suggestion does not seems intuitive, but you can take look on xdebug - function trace
Once you have xdebug installed and enabled, you can using all sort of configuration to save the profiling into a disk file and you can retrieve it later. Such as profiling results for different URL save into different disk file.
To monitoring file system related functions, you can do a parse of the text file(profiling results) and do a count of matchable functions (programmable or manually)
The way I would do it would be to create a custom function that wraps around the one you need.
function custom_file_get_contents($filename) {
$GLOBALS['file_get_contents_count']++;
return file_get_contents($filename);
}
And just replace all of your calls to file_get_contents with custom_file_get_contents. This is just a rudimentary example, but you get the idea.
Side note, if you want to count how many files your script has included (or required), see get_included_files()
You can use Xdebug to log all function calls
Those so-called "function traces" can be a help for when you are new to an application or when you are trying to figure out what exactly is going on when your application is running. The function traces can optionally also show the values of variables passed to the functions and methods, and also return values. In the default traces those two elements are not available.
http://www.xdebug.org/docs/execution_trace
Interesting question. I'd start with the stream_wrapper ... try to replace them with custom classes.
There is a pecl extention called ADB (Advanced PHP Debugger) that has tow functions that would be very useful for a cse like this - override_function() and rename_function(). You could do something like this:
rename_function('file_get_contents', 'file_get_contents_orig');
function file_get_contents($filename) {
logRequest();
return file_get_contents_orig($filename);
}
It looks like ADB is pretty easy to install, too.
See http://www.php.net/manual/en/book.apd.php