I am often using echo to debug function code:
public function MyFunc() {
// some code...
echo "OK";
// some code...
}
How can I check that my function print's/echo's something?
(pseudo code):
MyFunc();
if (<when something was printed>){
echo "You forgot to delete echo calls in this function";
}
This should work for you:
Just call your functions, while you have output buffering on and check if the content then is empty, e.g.
ob_start();
//function calls here
MyFunc();
$content = ob_get_contents();
ob_end_clean();
if(!empty($content))
echo "You forgot to delete echos for this function";
You could create a $debug flag and a debuglog() function, which checks for the debug flag and only then echos the message. Then you can toggle your debug messages on and off from one location.
define('DEBUGMODE', true); // somewhere high up in a config
function debuglog($msg){
if( DEBUGMODE ){ echo $msg; }
}
Should you ever want to get rid of your debug echos, you can search for "debuglog(" and delete those lines of code. This way you won't accidentally delete any echo statements that are required in normal execution or miss any debug echo statements that should really have been removed.
It's the bad way checking if something is echoed.
You can set a variable named is_echoed to 1 or you can return the value
public $is_echoed = 0;
//rest
$this->is_echoed = 1;
or
function myFunc()
{
return "OK";
}
if(myFunc() == 'OK')
//rest
You can use var_dump() and die() to debug your code more efficiently.
$test = "debud test";
public function MyFunc($test)
{
// some code...
var_dump($test); die();
// some code...
}
Reference:
http://php.net/manual/en/function.var-dump.php
http://php.net/manual/en/function.die.php
Why do you want to try such an extensive process of seeing if something has been echoed or not?
For debugging you can definitely use echo to see if the particular block is being hit during a particular use-case. But I would suggest you use flags and return the values to the calling function.
function xyz () {
if (something) return some_value;
else return some_other_value;
}
There is no particular need to have variables and use space in storing a 0 or 1 when you can just return a hard-coded literal.
I would suggest to you to use something like log4php [1]
But if not, I use a function like this:
define('DEBUG', true);
function debug($msg){
if(DEBUG){ echo $msg; }
}
Or something like this to see the log in the browser console:
function debug_to_console( $data ) {
if ( is_array( $data ) )
$output = "<script>console.log( 'Debug Objects: " . implode( ',', $data) . "' );</script>";
else
$output = "<script>console.log( 'Debug Objects: " . $data . "' );</script>";
echo $output;
}
Related
With my function what I have written I try thereby 2 things.
The links should be called like this http://localhost/?login=Bla, Now it is like this http://localhost/login,php?login "Bla
Next I would have asked, in my function a 1 is given after each call. I just can't figure out where this comes from, I've been sitting on this problem for a long time.
Output with the 1
This is the code with which I can call the pages
function Seite($pagename, $lay){
function Seite($pagename, $lay){
$path = "$lay/$pagename.php";
if (file_exists($path)) {
openSeite($path);
}
}
function openSeite($pageurl){
$fc = require($pageurl);
echo $fc;
}
function echopage($slug, $fade){
// $slug = ?SLUG=Seite
// $fade = Ordner des Layout
$page = isset($_GET["$slug"]) ? $_GET["$slug"] : "error";
$contente = seite($page, "$fade");
echo $contente;
}
I call the content on the index.php with
<? echopage("login", "admin/layout"); ?>
isset($_GET["$slug"]) returns a 1 because it is set (true), write a traditional conditional with the echo inside the if statement.
*Better Yet assign your output to a variable and concatenate the values accordingly.
$output = NULL;
if(isset($_GET["$slug"]){
$contente = seite($page, "$fade");
$output .= $contente;
}else{
//handle error
}
HTML:
<?=$output?><!--Output your displayed text held in the variable-->
ISSUE:
$page = isset($_GET["$slug"]) ? $_GET["$slug"] : "error";
You are essentially returning the set value, which is 1 also true.
From php manual for value: Returns TRUE if var exists and has any value other than NULL. FALSE otherwise.
You can test this by simply writing out a line of code echo isset($var); and checking the test php page. Then try defining a variable and doing the same thing. $var = "this is set"; then echo isset($var);, you will get a 1.
I have an HTML string mixed with PHP codes. so i want to just do evaluation of the codes that it possible and replace it back there. My idea is something like this :
$html='Hi it <b>PAPION</b>. Now timestamp is <?php echo time(); ?>. have a good time.';
$html = preg_replace_callback('/(<\?php)(.*?)(\?>)/ims',function($matches){
try {
ob_start();
eval($matches[2]);
return ob_get_clean();
} catch(Exception $e) {
return "";
}
}, $html);
and it works fine.
But if my code have an error, like this:
$html='Hi it <b>PAPION</b>. Now timestamp is <?php echo xxtime(); ?>. have a good time.';
$html = preg_replace_callback('/(<\?php)(.*?)(\?>)/ims',function($matches){
try {
ob_start();
eval($matches[2]);
return ob_get_clean();
} catch(Exception $e) {
return "";
}
}, $html);
instead of just leaving the place blank, it will make the $html string blank.
PHP >5.4
any way to handle it?
Best regards!
you set $html to "" in catch . must change your code like follow :
$html='Hi it <b>PAPION</b>. Now timestamp is <?php echo xxtime(); ?>. have a good time.';
preg_match('/(<\?php)(.*?)(\?>)/ims', $html, $matches);
$html = str_replace($matches[2], getEvalOutput($matches[2]), html);
echo "html is ".$html;
function getEvalOutput($matche){
try {
ob_start();
eval($matche);
return ob_get_clean();
} catch(Exception $e) {
return " ERROR happened";
}
}
you get fatal error and you must handle somehow that; this is just a test code for you to understand the way:
<?php
$phpCode = "
<?php
set_error_handler('myErrorHandler');
register_shutdown_function('fatalErrorShutdownHandler');
function myErrorHandler(\$code, \$message, \$file, \$line) {
echo \$message;
}
function fatalErrorShutdownHandler()
{
\$last_error = error_get_last();
if (\$last_error['type'] === E_ERROR) {
// fatal error
myErrorHandler(E_ERROR, \$last_error['message'], \$last_error['file'], \$last_error['line']);
}
}
\$html='Hi it <b>PAPION</b>. Now timestamp is <?php echo xxtime(); ?>. have a good time.';
\$html = preg_replace_callback('/(<\?php)(.*?)(\?>)/ims',function(\$matches){
try {
ob_start();
eval(\$matches[2]);
return ob_get_clean();
} catch(Exception \$e) {
}
}, \$html);
echo \$html;";
file_put_contents('a.php', $phpCode);
$x = exec( 'php a.php');
echo $x;
/* delete the file */
unlink('a.php');
As #user122293 said, the problem is about difference between fatal errors and other errors.
In PHP <7 fatal errors are not catch-able.
Also, there is no any Exception for fatal errors even in PHP >=7
Now we have some ways (from best to worst):
A) Making sure we use PHP 7 or higher and change the code to something like this :
$html='Hi it is <b>PAPION</b>. Now timestamp is <?php echo time(); ?>. have a good time. a can be: <?php a=b*2 ?>. and wrong timestamp is <?php xxxxtime(); ?>.';
$html = preg_replace_callback('/(<\?php)(.*?)(\?>)/ims',function($matches){
try {
ob_start();
eval($matches[2]);
return ob_get_clean();
} catch(Throwable $e) {
return "";
}
}, $html);
echo $html;
to output will be:
Hi it is PAPION. Now timestamp is 1570282086. have a good time. a can be: . and wrong timestamp is .
the important part in my case was using Throwable / Error in catch. as the explanation here: https://stackoverflow.com/a/48381661/7514010
B) & C) If we have access to exec function. we try the code first, then use it. or even save the file temporary and execute it for test. (Look crazy!)
or
Send the code as a query to a tester and get the result and then run it. (It can not work because some PHP code tags can depend to each other and should evaluate in same script.)
Both explained here : https://stackoverflow.com/a/33531067/7514010
D) Using register_shutdown_function + crazy way to force PHP 5 to at last have get the html again or even run next lines.
Like this example :
https://3v4l.org/0R7dq
+E) Make a function for parsing manually before eval or include using regex parsing and function_exists or method_exists or etc... or any library.
I've been looking up how I can debug PHP code in Chrome or Firefox but I can;t really find a solution. This is my PHP:
<?php
if(isset($_POST["data"]))
{
$var = $_POST["data"];
print "your message: " . $_POST["data"];
if(!empty($_POST['ip.data'])){
$data = $_POST['ip.data'];
$fname = mktime() . ".txt";//generates random name
$file = fopen("upload/" .$fname, 'w');//creates new file
fwrite($file, $data);
fclose($file);
}
}
?>
I want to be able to see the output of print "your message: " . $_POST["data"]; or any errors in Chrome or Firefox. I've tried Firefox Quantum that should be able to debug php? Anyways, how can I console log this?
The first step is to recognize that PHP, which is generally a server side language is a completely different context than the browser's console, which is fundamentally Javascript. Thus, to show messages to the browser's console from the server, you will need to find some way to communicate those messages (e.g., errors) to the browser.
At that point, you might consider something as simple as embedding a script tag with your PHP:
function debugToBrowserConsole ( $msg ) {
$msg = str_replace('"', "''", $msg); # weak attempt to make sure there's not JS breakage
echo "<script>console.debug( \"PHP DEBUG: $msg\" );</script>";
}
function errorToBrowserConsole ( $msg ) {
$msg = str_replace('"', "''", $msg); # weak attempt to make sure there's not JS breakage
echo "<script>console.error( \"PHP ERROR: $msg\" );</script>";
}
function warnToBrowserConsole ( $msg ) {
$msg = str_replace('"', "''", $msg); # weak attempt to make sure there's not JS breakage
echo "<script>console.warn( \"PHP WARNING: $msg\" );</script>";
}
function logToBrowserConsole ( $msg ) {
$msg = str_replace('"', "''", $msg); # weak attempt to make sure there's not JS breakage
echo "<script>console.log( \"PHP LOG: $msg\" );</script>";
}
# Convenience functions
function d2c ( $msg ) { debugToBrowserConsole( $msg ); }
function e2c ( $msg ) { errorToBrowserConsole( $msg ); }
function w2c ( $msg ) { warnToBrowserConsole( $msg ); }
function l2c ( $msg ) { logToBrowserConsole( $msg ); }
if ( 'POST' === $_SERVER['REQUEST_METHOD'] ) {
if ( isset( $_POST['data'] ) ) {
d2c( "Your message: {$_POST['data']}"
e2c( "This is an error from PHP" );
w2c( "This is a warning from PHP" );
l2c( "This is a log message from PHP" );
...
}
}
But this will be a fundamentally weak and brittle approach. I would suggest instead tailing your log files on the server directly. If you are after some color, consider using clog, lwatch, or grc:
$ grc tail -f /var/log/syslog
echo "console.log( 'Debug Objects: " . $output . "' );";
I ran through the same problem recently, just couldn't find a simple enough way without installing some large external package.
I first tried the obvious way:
<?php echo "<script>console.log(".$myVar.")<script>" ?>
but it only works with scalar types. For example:
<?php
$arr = [ 'x' => 42 ];
echo "<script>console.log(".$arr.")</script>";
?>
will output to the html
<script>console.log(Array)</script>
a solution to this is to use json_encode on the variable in the php side, then JSON.parse it in the javascript and finally console.log.
However this approach fails to capture non public properties of objects:
<?php
class Test {
private $x = 42;
public $y = 13;
}
$obj = json_encode(new Test());
echo "<script>console.log(JSON.parse('".$obj."'))</script>";
?>
will output to the browser console:
{y: 13}
Because private/protected fields can't be accessed by json_encode.
The solution here is either to add a __toString method to your class where you properly expose those fields as strings, or use some hack like calling var_export then process the output string to make it json_encode-able.
I ended up writing a small helper using the latter approach, and an output prettifier in the javascript side
Leaving the link here if anyone wants to use it.
If you want to see errors on an Ubuntu machine and you run an Apache server, you can constantly monitor and output changes to the error.log file in the apache folder with this command:
tail -f /var/log/apache2/error.log
If you have a server running on apache then this will output any errors occurred.
The tail command simply outputs the last 10 lines of a file and updates when new data is piped into the file.
I hope will help:
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
Try this
<?php
function temp()
{
if(isset($_POST["data"]))
{
$var = $_POST["data"];
print "your message: " . $_POST["data"];
if(!empty($_POST['ip.data'])){
$data = $_POST['ip.data'];
$fname = mktime() . ".txt";//generates random name
$file = fopen("upload/" .$fname, 'w');//creates new file
fwrite($file, $data);
fclose($file);
}
}
}//function
?>
<script>
console.log(".<?php temp(); ?>.");
</script>
On Chrome, you can use phpconsole which works quite well.
If anybody knows of something similar for Firefox Quantum please comment.
ok so im here trying to practice some php (im a super beginner) and so long story short,
i put form elements in one page, passed it to the process php.
Im just messing aound trying to see what ive learned so far. i dont get any errors, just dont understand why it doesnt work.
<?php
$yourname = htmlspecialchars($_POST['name']);
$compname = htmlspecialchars($_POST['compName']);
$response = array("please enter correct information","hmm" . "$yourname");
function nametest() {
if (!isset($yourname)){
$yourname = $response[0];}
else {
$yourname = $response[1];;
}
}
?>
<?php nametest(); ?>
what im trying to do is, that if the name isnt set, to make a variable equal to a value inside response.
Try
function nametest() {
if (!isset($yourname)){
$yourname = $response[0];
} else {
$yourname = $response[1];
}
return $yourname;
}
print nametest();
The function needs to return a value to be printed. I also noticed you have two ;; behind line 5.
Because you are assigning $yourname and $compname in the first two lines:
$yourname = htmlspecialchars($_POST['name']);
$compname = htmlspecialchars($_POST['compName']);
UPDATE You can check if these are set in POST, and therefore not need to check them later:
$yourname = isset($_POST['name']) ? htmlspecialchars($_POST['name']) : "oops, no value";
$compname = isset($_POST['compName']) ? htmlspecialchars($_POST['compName']) : "oops, no value";
They will always be set, even if NULL or empty. So, your later calls to isset() will always be true.
Instead, you may check if they are empty with the empty() function:
UPDATE Not necessary according to corrections in comments. Your isset() should work.
// Check with empty()
// but still won't work properly. keep reading below...
function nametest() {
if (!empty($yourname)){
$yourname = $response[0];}
else {
$yourname = $response[1];;
}
}
However, there is another problem here of variable scope. The variables are not available inside the function unless you either pass them in as parameters or use the global keyword:
// $yourname is passed as a function argument.
function nametest($yourname, $response) {
if (!empty($yourname)){
$yourname = $response[0];}
else {
$yourname = $response[1];;
}
}
Getting there... Now your function assigns $yourname, but it doesn't return or print any value. Add a return statement, and then you can echo out the result:
function nametest($yourname, $response) {
if (!empty($yourname)){
$yourname = $response[0];}
else {
$yourname = $response[1];;
}
// Add a return statement
return $yourname;
}
// Now call the function, echo'ing its return value
echo nametest($yourname, $response);
Variable Scope is the biggest mistake here, your function can not 'see' the variables that you created outside of it, do this:
<?php
.
.
.
function nametest($yourname, $response) { // This creates two new variables that
// are visible only by this function
if (!isset($yourname)){
$yourname = $response[0];
} else {
$yourname = $response[1]; // Get rid of the extra semicolon
}
return $yourname; // This $yourname is only visible by this function so you
// need to send it's value back to the calling code
}
?>
<?php nametest($yourname, $response); ?> // This sends the values of the
// variables that you created at the
// top of this script
Why is showphp_Smartfm() Not echoing at all.
foreach($response->quizzes as $quiz)
{
echo $quiz->question; // not echoing
echo $quiz->answer; // not echoing
}
Followup Question to Navigating objects and arrays
http://github.com/klanestro/Vortoj
<html>
<body>
<?php
// Created by Talisman 01/2010 ★✩
$vorto = $_GET['vorto']; // Get the Word from Outer Space and Search for it!
if (isset($vorto))
{
echo " Your Direct search was " . $vorto . ' <br></br> ';
} else {
$Help = "No Vorto -> add ?vorto=TheWordYouWant to the end of this website";
echo $Help;
}
// Now Lets Search Alex's Vortaro, It uses jsonp
// ex. http://vortaro.us.to/ajax/epo/eng/petas/?callback=?
/* Future Feature inproved language functinality */
// I used the capital AV to denote variables belonging to Alex's Vortaro
// #Plans for ( traduku.net, tn
// :apertium.org,ap // I think its apertium.org
// :reto-vartaro,rv
// each root word has an xml file, but how to you find this xml file?
// there is a xml link on the bottom of a search result, but I can't figure
// out a way to get to this info.
// :project gutenburg, pg
// :google books, gb
// BUT NEXT UP ЄЭ smart.fm
// it also assumes epo-eng
function getphp_AlexVortaro ($vorto)
{
$AVurl1 = "http://vortaro.us.to/ajax/epo/eng/";
$AVurl2 = "/?callback=";
$AVfinalurl= $AVurl1 . $vorto . $AVurl2;
$AVcontent = file_get_contents($AVfinalurl) ;
// Now we need to trim the () jsonp to json
$AVcontent = substr($AVcontent, 1);
$AVcontent = substr($AVcontent,0,-1);
$AVDecode = json_decode($AVcontent);
return ($AVDecode);
}
function getphp_Smartfm($vorto)
{
$SFurl="http://api.smart.fm/items/matching/";
// $SFurl2=urlencode($vorto); // +".json";
$SFurl3="?language=eo&translation_language=en";
$SFfinalurl = $SFurl . $vorto . ".json" . $SFurl3; // you can change .json to .xml
$SFcontent = file_get_contents($SFfinalurl);
$SFDecode = json_decode($SFcontent);
return ($SFDecode);
}
$AVvorto = getphp_AlexVortaro ($vorto);
$SFvorto = getphp_Smartfm($vorto);
function showphp_AlexVortaro ($AVvorto)
{
$AVvortoshow = $AVvorto->text;
echo $AVvortoshow;
}
showphp_AlexVortaro ($AVvorto);
function showphp_Smartfm($SFvorto)
{
// $objects is the array with all those objects
foreach($SFvorto as $object)
{
echo $object->cue->language; // language
foreach($object->responses as $response)
{
// if there are no quizzes, we skip the part below
// we skip it because $object->quizzes will produce a warning or a notice
// if "quizess" is not a member of the $object
if(!isset($object->quizzes))
{
continue;
}
// quizess
foreach($response->quizzes as $quiz)
{
echo $quiz->question; // question
echo $quiz->answer; // answer
}
}
}
}
showphp_Smartfm($SFvorto);
?>
</body>
</html>
This fixed it
- if(!isset($object->quizzes))
0
+ if(!isset($object->responses))
Go here
http://github.com/klanestro/Vortoj/commit/625fce9ffbd2a4d45d7b8dffddff6986fe521a00#comment_43364
Start doing 'echo-debugging'.
print_r($response);
print_r($response->quizzes);
foreach($response->quizzes as $quiz)
{
echo $quiz->question; // question
echo $quiz->answer; // answer
}
Maybe there are no $response->quizzes
Maybe the question and answer are empty string
Maybe this code is never being reached
Maybe it's outputting inside an HTML tag and you never thought to check View Source
Maybe it's dying way earlier in the script and you don't have error reporting turned on.
Enable all the error reportings:
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
//or directly edit your php.ini !
and try with:
foreach($response->quizzes as $quiz)
{
var_dump($quiz->question); // question
var_dump($quiz->answer); // answer
}
and see what is going on