Is there a way to achieve the following?
$myvar = 'x';
debug($myvar);
// outputs the following
// myvar value is x
Obviously, for this to happen, the debug function needs to be able to get the variable name passed to it.
Is there a magic constant for that?
And if there isn't, please recommend alternative ways that would simplify the debugging.
Of course, I'm aware of the option where you pass the variable name as a separate argument,
debug('myvar',$myvar);
but my goal is exactly avoid doing that.
Displaying variable name and its value for variable in global scope
Yes, there is, but you will need to pass the name instead:
function debug($var_name) {
printf('%s value is %s', $var_name, var_export($GLOBALS[$var_name], true));
}
or, if you want only value without the parsable formatting:
function debug($var_name) {
printf('%s value is %s', $var_name, $GLOBALS[$var_name]);
}
Displaying variable name and its value for variable in local scope
Attention: This works only for variables in global scope. To do the same for local scope, you will probably need a solution employing get_defined_vars(), like that:
printf('%s value is %s', $var_name, get_defined_vars()[$var_name]);
This cannot be simply enclosed within debug() function. This is because get_defined_vars() returns array representing variables in the scope where get_defined_vars() is called, and we do not need the scope where debug() is defined, don't we?
Unified solution
Unified solution could use global scope as default, but also accept some array representing local scope, so the definition could be:
function debug($var_name, $scope_vars=null) {
if ($scope_vars === null) {
$scope_vars = $GLOBALS;
};
printf('%s value is %s', $var_name, var_export($scope_vars[$var_name], true));
}
and then you can call it like that in global scope:
debug('myvar');
or like that in local scope, passing local scope array:
debug('myvar', get_defined_vars());
Working example
For working example see this demonstration: http://ideone.com/NOtn6
Does it help?
There is also great Google Chrome extension PHP Console with php library that allows to:
See errors & exception in Chrome JavaScript console & in notification popups.
Dump any type variable.
Execute PHP code remotely.
Protect access by password.
Group console logs by request.
Jump to error file:line in your text editor.
Copy error/debug data to clipboard (for testers).
Recommend everyone!
var_dump($my_var);
this is known as print debugging and considered as a very inefficient way for at least four reasons: you waste your time adding and then removing debugging code, debugging code slows down your web, not only the process where you're debugging, you can forget to remove the code after debugging is finished, it's takes time to find and analyze the results -- you see them in the continuous log(s) on the server.
A better aproach is to install special debugger extension and work with your code from an IDE inteded for php like PHPEd
Related
I'm trying to build a static code analysis tool and I would like to check if the variables in a file are defined. Currently I'm using nikic/PHP-Parser (https://github.com/nikic/PHP-Parser), but I'm not sure if what I'm attempting is even possible.
So my question is: is it possible to check whether is (possibly) set. So does the variable contain a different value than null? Since the code is not executed in static analysis I feel like it might be impossible to "guess" whether the variable might be null, before giving it to a function for example.
An example:
$page = Expertise::find(get_the_ID());
$relatedNews = $page->connectedNews->take(-3)->reverse();
The second line might give us an exception in this case, when $page turned out to be null. I would like to detect these kinds of instabilities in the code using static analysis.
Here's a piece of code of what I'm attempting using PHP-Parser.
class NodeVisitor extends NodeVisitorAbstract
{
public function enterNode(Node $node)
{
if ($node instanceof Node\Expr\Variable) {
// is not null (is set)
// or if that's not possible: is defined before reference?
}
}
}
Edit: to be more clear on why I'm doing this, I'm trying to build an application that detects possible 500 errors without knowing anything about the execution of the code.
I have the following method I want to test:
class SomeObject {
public function actionFromSomeController() {
$obj = new OtherObject();
$obj -> setAttributes();
$obj -> doAction();
}
}
class OtherObject {
private $_attr;
public function setAttributes() {
$this -> _attr = 'something';
Database :: execute('INSERT INTO table VALUES (' . $this -> _attr . ')');
$fileObj = new FileObj();
$content = $fileObj -> getSomeFileContent();
// do something else
}
public function doAction() {
echo $this -> _attr;
}
}
Now I want to test this method, its output depends on database content and one file on the server. It does a lot of things on the way, and the output is just one ID and success => 1.
How should I test it properly?
Some ideas on how to test small code pieces like this:
Generate test-data and pass it to your methods (also, fake database return data or file contents)
Use echo / var_dump() / die() to check property and variable content at different positions in your methods
Also use these commands to check whether execution reaches a certain point (for example to see whether a function got called or not)
If something doesn't work as expected without an error message: Check line by line with the above methods until you find the problem
Consider using interfaces and dependency injection if your code gets bigger - this is a bit over-the-top for this amount of code, but can be a tremendous time-saver when your application becomes big
Testing is never an automatic process and you will always have to think about what makes sense to do and what not. These things to do are never magic but basic PHP.
You should consider letting your scripts throw errors/exceptions if something goes wrong. Writing "silent" applications is almost never good since you can, if you really need a silent execution for production environments, just turn off error reporting and have the same effect. Many PHP functions return something special on failure and/or success and you can check for this. Database handlers do so, too. Do yourself a favor and use these return values!
In other words, say I have
$existingVariable = 'This is set';
echo thisFunction($existingVariable, $nonExistingVariable);
//included file
function thisFunction($existingVariable){
echo $existingVariable;
}
$nonExistingVariable is no longer there because the included file has changed.
So the way I understand it, $nonExistingVariable would = '' or NULL, right? Does this have any real impact on my code? I'll remove them (or add them back to the included file) before release, but I was just curious if having non-existing variables as an argument risked functionality issues.
It will not affect the function of your code, unless you are using func_get_args(); to work with your arguments instead of just specifying them (you are specifying them, so it won't have any affect)
I.E. you could be doing:
function test() {
$args = func_get_args();
$b = $args[0];
$c = $args[1];
echo "$b\n$c";
}
test('dog','cat');
outputs:
dog
cat
It will affect the readability and user-friendliness of your code moving forward though, as you may try and copy and paste a function call from an old area of code, and get stuck trying to figure out why the variable isn't getting passed into the function (because its no longer an argument).
Why not just remove it, if its not being used anymore?
if the variable doesn't exist then yes PHP will give you an error. "Undefined Variable". You can assign a NULL value, $nonExistingVariable= NULL; Or you can do
if (!empty($nonExistingVariable))
To prevent errors
in php i wrote my own debug function which have two arguments: text and a level of message. However i could be also you the php functions for triggering errors. But to debug in development i use sometimes like this:
debug($xmlobject->asXML(),MY_CONSTANT);
now i want to know whether it is a lack of performance in non debug executing because the arguments are calculated indepent whether they will be used inside function? and how to do that right that is only calculated if i need?
Thanks for your help,
Robert
If you write the following portion of code :
debug($xmlobject->asXML(),MY_CONSTANT);
Then, no matter what the debug() function does, $xmlobject->asXML() will be called and executed.
If you do not want that expression to be evaluated, you must not call it; I see two possible solutions :
Remove the useless-in-production calls to the debug() function, not leaving any debugging code in your source files,
Or make sure they are only executed when needed.
In the second case, a possibility would be to define a constant to configure whether or not you are in debug-mode, and, then, only call debug() when needed :
if (DEBUG) {
debug($xmlobject->asXML(),MY_CONSTANT);
}
Of course, the makes writting debbuging-code a bit harder... and there is a bit of performance-impact (but far smaller than executing the actual code for nothing).
The arguments are sended by value, ergo the method ->asXML() is executed always.
I'm trying to reduce the warnings that are sent to my apache server log.
One warning is:
Call-time pass-by-reference has been deprecated.
It is hard for me to imagine why this was deprecated since it is such a useful programming feature, basically I do this:
public function takeScriptsWithMarker(&$lines, $marker) {
...
}
and I call this function repeatedly getting results back from it and processing them but also letting the array $lines build up by being sent into this method repeatedly.
To reprogram this would be extensive.
I don't want to just "turn off warnings" since I want to see other warnings.
So, as call-by-reference is deprecated, what is the "accepted way" to attain the functionality of this pattern: namely of sending an array of strings into a method, have them be changed by the method, then continuing to use that array?
Actually, there's no problem with the way you define the function. Is a problem with the way you call the function. So for your example, instead of calling it like:
takeScriptsWithMarker(&$lines, $marker);
You'd call it like:
takeScriptsWithMarker($lines, $marker); // no ampersands :)
So the feature is still available. But I don't know the reason behind this change.
like noted above in a previous answer, the issue is at CALL time, not definition time.. so you could define a function as:
function foo(&$var1,$var2,$var3=null){
// procesing here
}
then call as:
$return = foo($invar1,$invar2);
your first invar is passed by reference, second one is not.
the error appears when you try to call like so:
$return = foo(&$invar1,$invar2);
You can set allow_call_time_pass_reference to true in your php.ini file. But it's a hack.
You could pass an array with a reference in:
public function takeScriptsWithMarker(array(&$lines, $marker))
which should only take a small amount of refactoring at the other end.
You could pass in the array, let it manipulate it, and then "return" it, instead of messing with the original reference. It shouldn't be too hard to just include a return and assignment.
public function takeScriptsWithMarker($lines, $marker) {
//...
return $lines;
}
Usage:
$lines = takeScriptsWithMarker($lines, $marker);