I have a universal function that I use for processing SQL. I am getting this error (just a few times a day, not frequently).
PHP Catchable fatal error: Object of class PDO could not be converted to string in...
Basically, an array of values is passed for a function that I am using, and I must have slipped up in my code and placed a PDO object in that array.
I need to make an array_filter function that checks if the variable is a PDO object. How do I do a simple if statement for this?
if($var == PDO)
Edit: Thanks for the great answers! In case anyone is interested, here is how I solved the problem. I was able to find where the invalid input was coming from.
$before=$original_array;
$after = array_filter($before, "find_error");
if(count($before)!=count($after)){
$error=print_r(debug_backtrace(false),true);
$arr=print_r($before,true);
send_message("admin#email.com","Error Report",$arr.$error);
//send_message is a simple function for sending emails. You could also write information to a txt file, etc.
}
function find_error($var){
return !($var instanceof PDO);
}
instanceof is used to determine whether a PHP variable is an instantiated object of a certain class:
if($var instanceof PDO) {
// your code
}
You can use instanceof for this.
if($var instanceof PDO){
//code here
}
However you say
I must have slipped up in my code and placed a PDO object in that array
I would recommend that you find and correct that slip up, otherwise you may be storing other problems for yourself as you continue development and possibly pass that array to other parts of your application.
Always cure the problem, rather than focusing on treating a symptom.
You are trying to cure the symptom instead of disease.
You are trying it out of mere speculation.
What are you trying to do is called "error message suppression". With desired if statement, already brought to you by good Samaritans, you're just closing your eyes pretending that there is no error in the program flow. While it remains.
A good programmer have to ask "how to track down the error and how to fix it", not "how to gag it".
So, you have to use debug_backtrace() to track the place where wrong data were added. this function have to be placed in the line marked by the error message you have.
Then you need to debug the code to make sure that your assumption of adding PDO result is right.
And finally fix the error.
It seems you managed to solve the problem the right way while I was writing this answer. But I got to leave it here for the future readers.
Related
This question already has answers here:
What is the use of the # symbol in PHP?
(11 answers)
Closed 6 years ago.
Inside a function I want to return a super global variable. It shows undefined. but when i use '#' before this super global variable then it is done. i want to know the actual use of '#'.
below is my code
public function getSession(){
return $_SESSION['login'];
}
There are some good use cases for using # in PHP.
One great example is if you're writing object oriented code and you want a clean object api that throws exceptions when something goes wrong. You're designing your class, and your object performs, say, a file_get_contents call in there. In order to maintain a nice, self-contained object api, you'll want to throw an exception when something goes wrong.
#file_get_contents(...)
Prefixing the # there allows you suppress the warning and ensure that the user of this object gets an exception. Instead, check for a false then throw your exception.
Why do you have to do this? Because php is a daft mix of functions that have no similarities or standards when compared with each other.
And with your specific example, which is nothing to do with #, you'd do an isset($_SESSION['login']).
You are looking at this the wrong way.
You should never access PHP superglobals from within the class to begin with. Instead you should use them as parameters, when creating the instance at the bootstrap stage of your code:
$request = new Request(
$_POST,
$_GET, new Session($_SESSION)
);
Kinda like this.
Then this $request instance is passes to the class, which is handling your user input. This has two major benefits:
ability to control and alter the perceived user input at runtime with affecting global scope (in cases when you are working in a legacy codebase, where parts of it are still based on include-oriented programming)
ability to test your code independently from the webserver
This boils down to:
"When is it okay to use #?"
And the answer is: virtually never.
The # operator suppresses errors, that's the only thing it does. There's basically no sane situation in which you'd ever want to suppress errors. Because error reports help you see, well, errors, mistakes, typos, wrong assumptions in your code. In this case your code is making the assumption that $_SESSION['login'] always exists. That assumption is apparently wrong, and PHP tells you about it with a notice. Either you have a bug in your code that causes this assumption to fail, or you need to change the assumption by using isset($_SESSION['login']).
The only legitimate case for using # is if you're working with 3rd party code where you expect errors and know what they mean and know they are harmless and which cannot be suppressed any other way.
First of all there is no need to return a super gloab just because its super global somethign like this
public function Foo(){
$_SESSION['login'] .= $_SESSIN['login'] . " blah blah";
}
its fine.
The # is using for turning off notices. And thats why whe you use assume its working because you had just turn off the notice :). The $_SESSION is still undefined . Take a look at http://php.net/manual/en/language.operators.errorcontrol.php
First off I know this question has gone around more than once here:
Why should I fix E_NOTICE errors?
Why should I fix E_NOTICE errors? Pros and cons
But the more that I fix all E_NOTICEs (as people say you should) the more I notice that:
I am micro-optimising
I am actually making more code and making my code harder to mantain and slower
Take an example:
Say your using the MongoDB PHP driver and you have a MongoDate object in a class var named ts within a class that represents a single row in a collection in your database. Now you acces this var like: $obj->ts->sec but PHP throws a fit (E_NOTICE) because ts in this case is not defined as an object in itself because this particular row does not have a ts field. So you think this is OK, this is desired behaviour, if it's not set return null and I will take care of it myself outside of the interpreters own robotic workings (since you wrap this in a date() function that just returns 1970 if the var is null or a none-object).
But now to fix that E_NOTICE as another developer really wants me to since having ANY E_NOTICEs is terribad and it makes the code slower to not do it according to the errors. So I make a new function in the $obj class called getTs and I give it 3 lines, literally to do nothing but check if the ts var is a MongoDate object and return it if it is...
WHY? Can't PHP do this perfectly fine for me within its much faster interpreter than having to do it within the runtime of the app itself? I mean every where I am having to add useless bumpth to my code, pretty much empty functions to detect variables that I actually just handle with PHPs own ability to return null or checking their instanceof when I really need to (when it is vital to the operation and behaviour of the said function) and don't get me started on the isset()s I have added about 300 lines of isset()s, it's getting out of hand. I have of course got to make this getTs functions because you can't do:
class obj{
public $ts = new MongoDate();
}
I would either have to store the ts within the __constructor (which I am not too happy about either, I am using a lot of magics as it is) or use a function to detect if it's set (which I do now).
I mean I understand why I should fix:
Undefined vars
Assigning properties of unset vars (null vars)
constant errors etc
But if you have tested your code and you know it is safe and will only work the way you desire what is the point in fixing all of the undefined index or none-object errors? Isn't adding a bunch of isset()s and 2 lines functions to your code actually micro-optimisation?
I have noticed after making half my site E_NOTICE compliant that actually it uses more CPU, memory and time now...so really what's the point of dealing with every E_NOTICE error and not just the ones that ARE errors?
Thanks for your thoughts,
You do certainly do get better performance by using isset(). I did some benchmarks, not too long ago, and just hiding errors came out to be about 10x slower.
http://garrettbluma.com/2011/11/14/php-isset-performance/
That said, performance usually isn't a critical factor in PHP. What does, personally drive me crazy is silent errors.
When the interpreter chooses to not flag something as an error (which could lead to instability) is a huge problem. PHP in particular has a tendency to
warn about things that should error (e.g. failure to connect to database) and
issue notices about things that ought to warn (e.g. attempting to access a member of a null object).
Perhaps I'm just overly opinionated about this kind of stuff but I've been bitten before by these silent errors. I recommend always including E_NOTICE in error reporting.
Whether or not you should fix them is certainly debatable, and will just depend on the return in your situation; eg, it's more important if the code will have a longer life-span, more devs, etc.
In general, assuming that your functions will be used (and mis-used) by someone else is the best practice, so you should do isset/!empty/is_object checks to account for this. Often, your code will find it's way into uses and situations you never intended it for.
As far as performance, Every time any kind of error is thrown--E_NOTICE included--the interpreter spins up the error handler, builds a stack trace, and formats the error. The point is that, whether or not you have them reporting, errors always slow execution; therefore, 2-3 function calls to avoid an E_NOTICE will still improve your performance.
Edit:
Alternatives for the above example
I wouldn't necessarily create extra objects to avoid the errors; you can gracefully avoid them without. Here are a couple of options:
1) Function that handles missing ts:
SpecialClass class {
funciton getTs () {
return !empty($this->ts) ? $ts->sec : false;
}
}
2) Deal with missing ts in template/procedure:
if (!empty($obj->ts->sec)) {
//do something
}
I particularly like empty() because you can use it to replace of (isset($var) && ($var or 0 != $var //etc)), saving multiple calls/comparisons and empty never throws notices for the target var or attribute. It will throw an error if you're calling it on a proptery/member of a non-existent variable.
I was wondering if it is always necessary to use something like is_array() before every foreach i do.
In case the variable is not an array, it throws an error.
So i always use:
if(is_array($users)) {
foreach($users as $user){
}
}
What would you recommend me?
Thanks.
Well if you know your code well enough, there should be no reason to have to check if it is an array.
Otherwise, if the variable changes type that often I would suggest tweaking your code a bit so it does not do that.
Other than that, using that if statement is the way to go.
If you're sure that something is an array or otherwise implements Iterable, you obviously don't need the extra if condition. If you're not sure, then obviously checking the type will make your code more reliable.
Some hacks I've seen include casting the variable to an array: (array)$users. This is not recommended though, it's better to explicitly check the type.
Also, if this is code inside a function you can use argument typing:
function mycode(array $users)
{
foreach ($users as $user) { }
}
When the function is called with the wrong type it will trigger an error.
Assuming this happens in a function:
function doSomethingWithUsers($users)
{
if(!is_array($users))
{
throw new Exception('$users is expected to be an array');
}
foreach($users as $user){
...
}
}
This way you'll immediately see whenever it's called with the wrong parameters.
In general, it's better not to.
A good general principle in programming is not to hide or ignore errors.
If a variable should be an array, it does you no service to specifically ignore the situation if it's not an array. Instead, it is better for you to be informed of the problem with the built-in error handling. Otherwise, you're not fixing the problem, just hiding its effects. This can make debugging subsequent problems difficult.
However, there's a number of assumptions here:
This is assuming that the variable is supposed to be an array. If you're using foreach () on it, I assume this to be the case. If you're running foreach () on something that might legitimately not be an array it might be an indication your code may need re-working.
Your error reporting and/or logging (reporting on a development server, logging on production) needs to be set up correctly in order to benefit from what PHP errors tell you. Specifically, it's almost never a good idea to ignore PHP warnings - despite being called "warnings" they usually indicate a failure which (in my opinion) should stop execution.
That said, it's not necessarily wrong to use an is_array() in front of a foreach ().
What would you recommend me?
Yes it is good idea and such considerations make you a defensive programmer :)
It's better for me:
foreach (is_array($arr) ? $arr : array() as $key=>$val) {
//..
}
I have an old application witch pops up an error at a certain location. The error is about an wrong set variable. Only from the error it is not possible to find the location where the variable is set wrong. Now my idea is to use reflections to find the location.
Is it possible to use reflections to find the code position at which a variable gets a certain value?
The idea: I have the name and the value of the variable. Now if both are matching a certain event should be triggered and echo the actual parsed file and line number.
Every ideas that help are appreciated.
Thank you,
-lony
P.S.: Is it possible even if the application is not really object oriented and uses a lot of spaghetti code?
I would be you do a debug_backtrace at the point where the error occurs and try to exploit the stack trace to see where the variable is changed. The debug_backtrace would give you a list of file included after it should be fairly easy to filter a list of line with a global search (i.e. grep)
var_dump(debug_backtrace())
if (variable == value) {
echo "variable equals value, line #whatever"+"<br/>";
}
Just place these at various points in code and see which ones display. Manually enter line numbers.
I found a solution to one of my problems.
The function debug_print_backtrace helped me finally debugging my spaghetti code. I found it by reading this post.
-Cheers
I have a function that looks like this
class NSNode {
function insertAfter(NSNode $node) {
...
}
}
I'd like to be able to use that function to indicate that the node is being inserted at the start, therefore it is after nothing. The way I think about that is that null means "nothing", so I'd write my function call like this:
$myNode->insertAfter(null);
Except PHP throws an error saying that it was expecting an NSNode object. I'd like to stick to using the strict data typing in my function, but would like to be able to specify a null-esque value.
So, short of changing it to function insertAfter($node) { }, is there a way I can pass something else to that function?
Update: I've accepted Owen's answer because it answered the question itself. Everyone else's suggestions were really good and I'll actually be implementing them in this project, thanks!
sure, just set a default "null"
function(NSNode $node = null) {
// stuff....
}
result being:
$obj->insertAfter(); // no error
$obj->insertAfter(new NSNode); // no error
$obj->insertAfter($somevar); // error expected NSNode
No, you can't pass something else to the function as that defeats the purpose of the static typing. In this situation, something like C# nullable would be nice i.e. NSNode?
I'd suggest creating NSNode::insertFirst() although I think that you have it the wrong way round, why is a node inserting itself, shouldn't the collection be inserting and taking the node as a parameter?
Better to have a function insertAtBeginning() or insertFirst() for legibility anyway.
"The way you think of it" may not be the way the next guy thinks of it.
insertAfter(null) might mean many things.
Maybe null is a valid value and insertAfter means place it after the index that contains the value null.