What is the best way to debug an array so that you can see what values are being stored and in what keys in the array they are being stored at? Also how do you make it so that it's easier to look at visually so that you don't have to keep looking through the array for the key and it's value in the one line print_r() function?
EDIT:
I now realize that print_r() is not the only solution to debugging arrays. So if you have alternate solutions that would be lovely as well to learn more about debugging.
EDIT2:
Ayesh K, ITroubs and Robert Rozas have mentioned both Krumo and Kint this far, if you have others feel free to post them. Also thanks to Raveren for writing Kint!
Every PHP developer should have a function for this. My function is below:
function r($var){
echo '<pre>';
print_r($var);
echo '</pre>';
}
To nicely print data, just call r($data);. If you want more detail, you could use this function:
function d($var){
echo '<pre>';
var_dump($var);
echo '</pre>';
}
here's mine...
demo: http://o-0.me/dump_r/
repo: https://github.com/leeoniya/dump_r.php
composer: https://packagist.org/packages/leeoniya/dump-r
you can restyle it via css if needed.
Everyone suggests print_r which is in core and works really well.
But when it comes to view a large array, print_r() drives me nuts narrowing down the output.
Give a try to krumo.
It nicely prints the array with visual formatting, click-expand and it also gives you the exact array key call that you can simply copy and paste.
<?php
krumo($my_array);
?>
Itroubs mentioned Kint as a better alternative to Krumo. (Thanks ITroubs!)
I use var_dump....now if you want some more, check out this site:
http://raveren.github.io/kint/
and
http://krumo.sourceforge.net/
The best practice to visually see the values/keys in an array is the following:
echo "<pre>".print_r($array,TRUE)."</pre>";
The true is required as it changes it into a string, the output will be:
array(
key1 => value,
key2 => value,
...
)
Quick solution: Open the source code of the page, and you'll see print_r's output in several lines and perfectly indented.
print_r is not one lined (it uses \n as new line, not <br>). Add a <pre>...</pre> around it to show the multiple lines.
print_r() uses \n as its line delimiter. Use <pre> tags or view the page's source code to make it look right. (on Windows, Linux works with \n)
You can either look source code or use var_dump() or print_r() with <pre>...</pre>
I personally, never liked all this fancy stuff, i use print_r() because it's not overwhelming and it gives enough information.
Here is mine:
if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] == 'Debug')
{
echo '<strong><i>FILE : </i></strong>'.__FILE__.'<strong> <i>LINE : </i></strong>'.__LINE__.'<pre>';
print_r($var);
echo '</pre>';
die;
}
This if statement is to ensure that other people don't see what you've printed.
There is a good add-on for Mozila-Firefox and Google Chrome called "user agent switcher", where you can create your custom user agents. So I create a user agent called "Debug", and when I'm working, I change the user agent.
If I use default user agent nothing will happen and the page wont die;, only you and people who also change the user agent to "Debug" will see the printed variable. This is helpful if you want to debug a problem in a production environment, and you don't want the page to die; and it is also good if other people are also working on the project and you don't want to interrupt them by killing the page.
Then I echo out the current File and Line, this is helpful when you work in a framework or CMS or any other big project with thousands of files and folders, and while debugging, if you might forget where you've typed die; or exit; and you need to remember where you've been and which variables you have printed.
I use the NetBeans IDE for PHP development, I have a macro set up so when you select a variable and use it, it will paste this debugging tool to the text editor and put the selection inside a print_r(); function. If you also use NetBeans, you can use this macro:
cut-to-clipboard
"if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] == 'Debug')"
insert-break
"{"
insert-break
"echo '<strong><i>FILE : </i></strong>'.__FILE__.'<strong> <i>LINE :</i></strong>'.__LINE__.'<pre>';"
insert-break
"print_r("
paste-from-clipboard
remove-line-begin
");"
insert-break
"echo '</pre>';"
insert-break
"die;"
You just need to select the $variable and use the macro.
To be honest, I'm surprised that print_r() (print human-readable). There are three native functions which each have their advantages and disadvantages in printing data to a document. As mentioned elsewhere on the page, wrapping your output in <pre> ... </pre> tags will be very beneficial in respecting newlines and tabbing when printing to an html document.
The truth is that ALL php developers, from newbie to hobbyist to professional to grand wizard level 999, need to have the following techniques in their toolbox.
Here is a non-exhaustive demo which exposes some of the differences.
var_export() is the format that I use most often. This function wraps strings in single quotes. This is important in identifying trailing whitespace characters and differentiating numeric types versus string types. To maintain the integrity of the output data and permit instant portability of the data into a runnable context, single quotes and backslashes are escaped -- don't let this trip you up.
print_r() is probably my least-used and the least-informative function when data needs to be inspect. It does not wrap strings in any kind of delimiting character so you will not be able to eyeball invisible characters. It will not escape backslashes, single quotes, or double quotes. It wraps keys in square braces which may cause confusion if your keys contain square braces originally.
var_dump() is uniquely powerful in that it expresses data types AND the byte count for strings. This is hands-down the best tool when there is a risk that you might have unexpected multibyte characters interfering with the success/stability of your script.
Depending on your php version and which function you use, you may see differing values with same input data. Pay careful attention to float values.
debug_zval_dump() very much resembles the output of var_dump(), but also includes a refcount. This native function is not likely to provide any additional benefit relating to "debugging an array".
There are also non-native tools which may be of interest (most of which I've never bothered to use). If you are using a framework, Laravel for instance, offers dd() (dump and die) as a diagnostic helper method. Some devs love the collapsed/expandable styling of this tool, but other devs loudly voice their annoyance at the tedious clicking that is necessary to expose nested levels of data.
As a sideways approach to printing iterable data, you could entertain the idea of echoing a json-encoded string with the JSON_PRETTY_PRINT. This may reveal some things that could cause trouble like multibyte and whitespace characters, but don't forget that this is literally "encoding" the data. In other words, it is converting data from one form to another and it will mutate certain occurrences in the process. Like var_export(), a json encoded string is an excellent form to maintain data integrity when it needs to be tranferred from one place to another (like from your project to your Stack Overflow question!).
Related
I am keeping record of every request made to my website. I am very aware of the security measurements that need to be taken before executing any MySQL query that contains data coming from query strings. I clean it as much as possible from injections and so far all tests have been successful using:
htmlspecialchars, strip_tags, mysqli_real_escape_string.
But on the logs of pages visited I find query strings of failed hack attempts that contain a lot of php code:
?1=%40ini_set%28"display_errors"%2C"0"%29%3B%40set_time_limit%280%29%3B%40set_magic_quotes_runtime%280%29%3Becho%20%27->%7C%27%3Bfile_put_contents%28%24_SERVER%5B%27DOCUMENT_ROOT%27%5D.%27/webconfig.txt.php%27%2Cbase64_decode%28%27PD9waHAgZXZhb
In the previous example we can see:
display_errors, set_time_limit, set_magic_quotes_runtime, file_put_contents
Another example:
/?s=/index/%5Cthink%5Capp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=ctlpy.php&vars[1][]=<?php #assert($_REQUEST["ysy"]);?>ysydjsjxbei37$
This one is worst, there is even some <?php and $_REQUEST["ysy"] stuff in there. Although I am able to sanitize it, strip tags and encode < or > when I decode the string I can see the type of requests that are being sent.
Is there any way to detect a string that contains php code like:
filter_var($var, FILTER_SANITIZE_PHP);
FYI: This is not a real function, I am trying to give an idea of what I am looking for.
or some sort of function:
function findCode($var){
return ($var contains PHP) ? true : false
}
Again, not real
No need to sanitize, that has been taken care of, just to detect PHP code in a string. I need this because I want to detect them and save them in other logs.
NOTE: NEVER EXECUTE OR EVAL CODE COMING FROM QUERY STRINGS
After reading lots of comments #KIKO Software came up with an ingenious idea by using PHP tokenizer, but it ended up being extremely difficult because the string that is to be analyzed needed to have almost prefect syntax or it would fail.
So the best solution that I came up with is a simple function that tries to find commonly used PHP statements, In my case, especially on query strings with code injection. Another advantage of this solution is that we can modify and add to the list as many PHP statements as we want. Keep in mind that making the list bigger will considerably slow down your script. this functions uses strpos instead of preg_match (regex ) as its proven to perform faster.
This will not find 100% PHP code inside a string, but you can customize it to find as much as is required, never include terms that could be used in regular English, like 'echo' or 'if'
function findInStr($string, $findarray){
$found=false;
for($i=0;$i<sizeof($findarray);$i++){
$res=strpos($string,$findarray[$i]);
if($res !== false){
$found=true;
break;
}
}
return $found;
}
Simply use:
$search_line=array(
'file_put_contents',
'<?=',
'<?php',
'?>',
'eval(',
'$_REQUEST',
'$_POST',
'$_GET',
'$_SESSION',
'$_SERVER',
'exec(',
'shell_exec(',
'invokefunction',
'call_user_func_array',
'display_errors',
'ini_set',
'set_time_limit',
'set_magic_quotes_runtime',
'DOCUMENT_ROOT',
'include(',
'include_once(',
'require(',
'require_once(',
'base64_decode',
'file_get_contents',
'sizeof',
'array('
);
if(findInStr("this has some <?php echo 'PHP CODE' ?>",$search_line)){
echo "PHP found";
}
I have following code:
<?php
$param = $_GET['param'];
echo $param;
?>
when I use it like:
mysite.com/test.php?param=2+2
or
mysite.com/test.php?param="2+2"
it prints
2 2
not
4
I tried also eval - neither worked
+ is encoded as a space in query strings. To have an actual addition sign in your string, you should use %2B.
However, it should be noted this will not perform the actual addition. I do not believe it is possible to perform actual addition inside the query string.
Now. I would like to stress to avoid using eval as if it's your answer, you're asking the wrong question. It's a very dangerous piece of work. It can create more problems than it's worth, as per the manual specifications on this function:
The eval() language construct is very dangerous because it allows
execution of arbitrary PHP code. Its use thus is discouraged. If you
have carefully verified that there is no other option than to use this
construct, pay special attention not to pass any user provided data
into it without properly validating it beforehand.
So, everything that you wish to pass into eval should be screened against a very.. Very strict criteria, stripping out other function calls and other possible malicious calls & ensure that 100% that what you are passing into eval is exactly as you need it. No more, no less.
A very basic scenario for your problem would be:
if (!isset($_GET['Param'])){
$Append = urlencode("2+2");
header("Location: index.php?Param=".$Append);
}
$Code_To_Eval = '$Result = '.$_GET['Param'].';';
eval($Code_To_Eval);
echo $Result;
The first lines 1 through to 4 are only showing how to correctly pass a character such a plus symbol, the other lines of code are working with the data string. & as #andreiP stated:
Unless I'm not mistaking the "+" is used for URL encoding, so it would
be translated to a %, which further translates to a white space.
That's why you're getting 2 2
This is correct. It explains why you are getting your current output & please note using:
echo urldecode($_GET['Param']);
after encoding it will bring you back to your original output to which you want to avoid.
I would highly suggest looking into an alternative before using what i've posted
This may seem like a really daft question, but what is the reason for the existence of the printf() function in PHP?
It seems to me that that using echo will achieve the exact same results, with the added bonus that you don't get confused if you have several variables being output on one line (true, you can use %1$s as opposed to just %s, but it can still get messey with a few variables all being declared).
I know you can also define the type of the variable, without the need to amend it before outputting the string, but to me that doesn't seem like enough to warrent creating a function.
Maybe I'm wrong, maybe I'm missing something obvious, but if someone can help me to understand why it exists (so that I know whether or not I should really be using it!) I'd appriciate it. Thanks.
echo is language construct, printf is a function. It means that so you won't be able to use echo in the same way as printf.
IT'S NOT JUST PERSONAL TASTE
Take a look to the manual pages for both functions:
echo: http://php.net/manual/en/function.echo.php
printf: http://php.net/manual/en/function.printf.php
This topic is discussed there, for example, you cannot call echo with variable functions. Moreover the way they get and manage the input is different. If you do not need the parameters FORMATTING provided by printf you should use echo (it's slightly faster).
Examples
I insist again on some keywords: formatting and function.
The use of printf isn't to concatenate strings or to build a string from placeholders but to do it with custom formatting (possibly from configuration, user inputs or whatever else).
I write some code to explain what I mean (original source in the links I posted).
This code is not valid, echo is not a function so it won't return the printed value (you may use print or sprintf for this but print does not provide string concatenation).
($some_var) ? echo 'true' : echo 'false';
Following code prints a formatted string, in this case the format comes from a literal variable but it may comes from (for example) a GET request or whatever else. Can you rewrite it with echo and the formatting string taken from the configuration?
%format = "%'.-15.15s%'.6.6s\n";
printf($format, $heading1, $value1);
printf() is a port of C's printf() function, so people who got a background writing C code are more familiar with the syntax and will prefer it.
However, most people who start with PHP find it rather confusing.
For comparison:
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));
(I used sprintf(), which is the same as printf but it won't actually print the string, it just returns it)
$query = "SELECT * FROM users WHERE user='" . mysql_real_escape_string($user) . "' AND password='" . mysql_real_escape_string($password) . "'";
It's just a matter of preference!
This is about separating static string and formatting, and data.
This separation is encouraged in every programming language that I know of because:
intent of programmer is clearer and enforced
intent is clear: When you read this you know what type is awaited for each field:
printf("a: %.2f, b: %s, c: %d", $a, $b, $c)
intent is enforced: silly type errors are limited (as for the security concerns).
it's more secure
Because it limits silly injection of unexpected meta-strings:
$avg = 3.1415;
// $avg = '3</td>pawned!';
printf("average: %.2f", $avg);
It's much worse in SQL...
usually much easier to read
Appart than you have more clues to the intent of the writer, the string
is clearly in one unique clear block. Data are cleanly listed one by one
after. You don't overuse things like ", . all over the place.
it's very powerfull
I'm curious to see how you would do the following without printf:
printf("%.2f %5d", $v1, $v2);
it's some sort of standard of programming
A lot of other programming languages (C, C++, Java, Python, Bash...) will have
similar printf format and way to treat strings.
So its good for you to know it, and for those who already know, it's easier.
And as a consequence there are plenty of docs and tutorials everywhere on the
subject, and a wikipedia page for it: print format string
The strings can be separated from your data automatically
And this means it's available for translation or syntax correction.
You'll find similar concerns with:
prepared statements in mysql that are now enforced with mysql_query being
deprecated in php 5.5 in favor for prepared statements.
All templating language: where you have the template usually in a different langage,
and the data the other side to render the template.
The more general topic is covered on wikipedia: string interpolation
A last precision:
echo does nothing more than outputing a string. And printf does string interpolation, and outputs a string.
So to be fair, we are here comparing building string via string concatenation vs string interpolation. As there's nothing wrong to output a string with echo. So this is not about echo but how you make your string. You are doing string interpolation even when using echo like this:
echo sprintf("avg: %.3f", $avg);
But then, well there are no more difference between this last form and:
printf("avg: %.3f", $avg);
printf probably exists because PHP was created in C, and printf is traditionally used to output formatted strings in C. printf can actually do a lot more than echo because it can output variables in a variety of formats including decimals to certain places and probably a lot more.
That being said, you can do anything that printf can do with some combination of PHP functions, and it may make more sense depending upon your background.
I'll just explain what I did so you get a clear difference, I'm not a PHP Pro, so maybe I'm wrong and there is a better or easier approach, and also my example may be not so useful to you as well.
I pass each string I want to translate to a function, and it returns the translated string, based on source string and current language, this way it would translate:
"The cat has %d kittens." (english) <=> "Katua %d kume ditu." (euskera)
The fact is that the splitted string for the echo couldn't be translated, as the part previous to the number is not the same for every language, so it must be translated as a "single entity".
It's legacy from C inherited by the PHP language
function http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/
printf takes input differently: you can provide a format string and then list all the required input (just like in C/C++).
'echo' and 'print' only take strings and are easier to use.
Your wish, Your style :)
NOT THAT:
as Others have said echo is a language construct and printf is a real function,
You can do lot with printf.
People coming from C/C++ background know a lot of format strings like %f, %d, %.2f and what not !!!!!
They would prefer printf to echo for this scenario as these floating point precison format and others will be at their finger-tips.
They wd prefer these over PHP's inbuilt format functions.
I'm merging two different versions of a translations array. The more recent version has a lot of changes, over several thousand lines of code.
To do this, I loaded and evaluated the new file (which uses the same structure and key names), then loaded and evaluated the older version, overwriting the new untranslated values in the array with the values we already have translated.
So far so good!
However, I want to be able to echo out the constructor for this new merged array so I can cut and paste it into the new translation file, and have job done (apart from completing the rest of the translations..).
The code looks like this (lots of different keys, not just index):
$lang["index"]["chart1_label1"] = "Subscribed";
$lang["index"]["chart1_label2"] = "Unsubscribed";
And the old..
$lang["index"]["chart1_label1"] = "Subscrito";
$lang["index"]["chart1_label2"] = "Não subscrito";
After loading the two files, I end up with a merged $lang array, which I then want to echo out in the same form, so it can be used by the project.
However, when I do something like this..
foreach ($lang as $key => $value) {
if (is_array($value)) {
foreach ($value as $key2 => $value2) {
echo "$lang['".$key."']"; // ... etc etc
}
}
}
..obviously I get "ArrayIndex" etc etc instead of "$lang". How to echo out $lang without it being evaluated..? Once this is working, can add in the rest of the brackets etc (I realise they are missing), but just want to make this part work first.
If there's a better way to do this, all ears too!
Thanks.
edit:
What I was really looking for was this:
"Note: Unlike the three other syntaxes, variables and escape sequences for special characters will not be expanded when they occur in single quoted strings."
So no need even to escape. May come in handy one day for someone... about merging the arrays, there's a great recursive array merging function on the PHP manual page for array_merge(), which also came in handy.
Thanks to whoever downvoted! Love you too.
Either escape the $: "\$lang" or use single quotes: '$lang'
Note that you really don't need to post a whole page of backstory, if your entire question just boils down to "how do I output a dollar sign in PHP"
there is var_export() function, but I do not understand the purpose of this terrible mess.
It's all too... manual
why not to use a gettext - an industry standard for multi-language site?
or at least some other format, more reliable than plain PHP one?
Programming code is not intended to be written automatically.
I would like to know if I can use a gt function on a variable with php?
eg. : echo _($var);
Feel free to. But you need to make sure the possible contents of the variable makes it into .po/.mo files. (one of the ways to do assure it is to create a dummy file never processed except for by xgettext, containing _("translate me"); expressions).
I don't think gettext will recognize a variable since it scans the source code. If you want to include variables in a string, it's better to use
sprintf()
For example
echo sprintf(_("There are %d results!"), $numResults);
In gettext, the translator will see
There are %d results!
so therefore it can easily be translated as long as he/she knows that %d is a variable. When the script gets executed, gettext will first replace the translation, and then sprintf will insert the variable $numResults. Good luck! I just got done internationalizing my site.