__toString() must not throw an exception error when using string - php

I am using Laravel 4 for a project I am working on. I need to retrieve the first comment from the post. I use the following code to do so.
$comments = Comment::where('post_id', $post->id)->first();
This successfully retrieves the first comment (I know that because I print_r-ed $comments and it returned all the right information).
However, the following line of code triggers the error __toString() must not throw an exception
<td>{{$comments->content}}</td>
When I print_r-ed that it returned type string, and returned the correct string as well. Why then would it even try to convert $comments->content to type string when it is already a string?

Based off the information you've given and my experience with Laravel I'd bet that the line of code causing the exception is not the line you've put in your question.
<td>{{$comments->content}}</td>
This exception is complaining about the view throwing an exception. If this particular line was the issue you'd get a more descriptive exception about how $comments->content can't be converted into a string. You've also already tested that it is indeed a string.
I'd recommend finding where your "View" object is being echoed to the view and change it like so.
{{ View::make('yourbladefile')->__tostring() }}
This worked for me by providing a more accurate and informative exception. For more info on your exception you should check out Why it's impossible to throw exception from __toString()?
It's what gave me the idea in the first place. I know it's not a perfect answer so please let me know if this works and I'll update my answer if this turns out not be the case. Good luck.

I know that this is an old question, but for future googlers (like me) there is another way to solve that error, and it is independent of your framework:
public function __toString()
{
try {
return (string) $this->attributeToReturn; // If it is possible, return a string value from object.
} catch (Exception $e) {
return get_class($this).'#'.spl_object_hash($this); // If it is not possible, return a preset string to identify instance of object, e.g.
}
}
You can use it with your custom class with no framework, or with an entity in Symfony2/Doctrine... It will work as well.

Related

Using count(array) causes Error to be thrown

I've got this line in code in module CMap.php which is part of the yii framework which should count the number of elements in array _d.
return count($this->_d);
Howver, if _d is an array[0] it raises the error:
Trying to obtain property of non object
Using PHP v5.3.3 (x86) which is the same version as installed on our webserver.
Any idea why this is happening? Thanks.
EDIT:
Changed the code to this:
try {
return null;
if ($this->_d==null)
return null;
else {
if(isset($this->_d[$key]))
return $this->_d[$key];
else
return null;
}
}
catch (Exception $e) {
return null;
}
And it still throws an errors on the first return null; line without entering the catch() block.
Let's break down the error message:
Trying to obtain property
A "property" is a field of some object, and "property access" is what you do with the -> operator. In your case, $this->_d.
of non object
In the expression $this->_d, we would say "_d is a property of $this". So "of a non-object" means the thing on the left of the -> operator is not an object.
So assuming the code you've posted is accurate, and not anonymized to the point where it's hiding the real error, your problem is that $this is not an object in that part of the code.
Note that this contradicts your claim that $this->_d is an empty array, because if $this is not an object, then $this->_d does not exist. So I strongly suspect that you're looking in the wrong place, or you've tried to simplify the description but missed out crucial details.
Ok, I'm going to close this thread off now.
The code posted in my OP wasn't buggy, and wasn't causing the error.
Complete red herring. What is happening is that the code running after this method (the code which calls this method) is throwing the error, but for some reason that code doesn't show up in my debugger. I can't step through it.
The first I see of any debugging is when a breakpoint in the ErrorHandler gets hit.
I'll raise a separate Question on how/why the YII framework is doing that.
Thanks for you comments guys.

PHP variable mysteriously changing from integer to string

I am trying to implement a catch-all exception handler in PHP such that it will set the status code of the response to the status contained in the exception (if present), but for some reason when I pass what is definitely an integer (because I am logging gettype()) into a function, it is somehow turning into a string on the way to that function because if I log its type immediately in the function it is now a string!
Clearly I don't know enough about PHP because this is confounding the heck out of me. Why on earth would this ever happen and how do I stop it from happening?
function qpGlobalExceptionHandler($e) {
$code = intval($e->getCode());
error_log("Global exception (".$code." ".gettype($code)."): ".$e->getMessage());
$this->sendReply($code, $e->getMessage(), false);
}
At this point in the error log I see:
Global exception (404 integer): CouchDB Error: not_found (deleted) …
But inside sendReply, which looks like this:
public function sendReply($responseCode,$responseText=false,$allowCaching=true) {
error_log("In sendReply. gettype(responseCode): ".gettype($responseCode));
// ...
}
In the error log I get:
In sendReply. gettype(responseCode): string
Now I know PHP can be weird, but what the heck?
Update: So I realized one problem, and that was that I was referencing $this from the global exception handler, which is not a member of any class. Strangely the call somehow still ended up making its way to the actual member function I wanted to call, but I'm guessing there must be some strange fallback logic PHP was doing to find the "best match" for the function call and in that logic the parameters ended up getting converted to strings somehow.
Anyhow I have ended up just taking a different approach and it's no longer a problem. I still have no idea what was going on though, so if there are any PHP pros out there who can enlighten me I'd still be happy to learn.

Catch error messages from standard PHP functions with a Unit test

A bit unclear on the title, but here we go.
I am running a unit test on a method that essentially runs a strpos(). Like this:
return strpos($this->getHeaderLine($headerName), $value) !== false;
Now I also want to see what happens if I supply it an empty value. When provide an empty string, I get the following message:
strpos(): Empty needle
This message in itself is clear enough, I don't want to throw an exception here. I do want to know if it returned this message though. How would I go about doing this or do I need to rewrite my method?
Try the following:
public function testWarning()
{
$this->expectException(PHPUnit_Framework_Error_Warning::class);
$this->expectExceptionMessage("Empty needle");
strpos('meh', '');
}
This test passes, but if you comment out the expectations, it fails. There are more related classes in PHPUnit framework, like PHPUnit_Framework_Error_Deprecated, PHPUnit_Framework_Error_Notice and so on.

How to handle this ErrorException in PHP

I'm trying to format user input with the following code:
$userInput="blalalbla";//assume the user is inputing wrong data, they are supposed to input it like "12:30"
try{
$timeStr=explode(":",$userInput);
$time=(new Datetime())->setTime($timeStr[0],$timeStr[1]);
}catch(ErrorException $e){
}
However, if the input is not in the right format, laravel4 will always fire an ErrorException and I have no way of catching it. Since the user input can be wrong in different ways, I thought this was the most elegant way of handling validation. As ridiculous as it sounds like, ErrorExceptions seem to be un-catchable. What other options do I have?
The actual error received in your code is a PHP Notice. You can't catch it because it isn't an exception at that point in time. Laravel defines the class Illuminate\Exception\Handler and uses PHP's set_error_handler() to turn PHP errors into ErrorExceptions.
To use a try/catch block in your controller, you'll have to throw the exception yourself in that area (or use code that throws exceptions). However, as most have commented, you should be doing appropriate input checking and sanitation prior to actually using the input in any code. Whether or not poor input throws exceptions is totally up to you.
set a global error handler
set_exception_handler (handler);
function handler($e) {
if($e instanceof TheExceptionYouWantToHandle) {
//then handle it
}
}

Handling errors in a class, what method should I use?

I have been dealing with PHP since 2000, but not very actively, and my knowledge of PHP5 is quite horrible. Recently I got my interest for webdevelopment back after a 5 year long break, and I started working on a project. I wrote a class for that project that became fairly large, but so far without any specific error handling.
The purpose of the class is to parse HTML files with a specific layout and handle its data, and it was more or less a training exercise for me to get back into the game. I started to rewrite the class now, and I decided it was time to be a little more professional about error handling than simply using die(), which I have been using a lot so far. I think we can all agree that is a terrible direction to take. I want the class to be quite project independent, so that I can distribute it to whoever wants to use it.
The HTML files I want to parse contain tables with specific bordercolors, trs with specific bgcolors, but the number of elements are dynamic. To validate that the HTML files actually have this specific pattern, I have the following sample (pseudo)code
public function Validate() {
$tables = getall('table', $this->data);
foreach ($tables as $table) {
if ($table->bordercolor != 'navy' && $table->cellspacing != 0) {
// Error
}
foreach ($tables->tr as $tr) {
if ($tr->bgcolor != '#fff') {
// Error
}
}
}
return true;
}
Where it says // Error, the HTML layout doesn't check out and my class should not attempt to parse it. Traditionally I would do this:
if ($table->bgcolor != '#fff') {
$this->error = 'Invalid HTML layout';
return false;
}
And from where I call the method I would use
if ($class->Validate() === false) {
exit_with_error($class->GetError()); // Simple return of $this->error
}
I've always thought it's a decent approach because of it's simplicity. However that's also a disadvantage as it doesn't really provide any in-depth information of the error apart from the text itself. I can't see where the error was triggered, what methods were called, etc.
Since I resumed my PHP hobby I have discovered exceptions. My problem with them is simply that I don't understand how to properly use them. And if I should use them at all. I would like my class to be portable; can I use exceptions to handle errors at all? And if yes, how can I communicate the errors (i.e. translate my traditional error handling)? Or perhaps there is an even better approach to take, which I don't know about.
Any help appreciated :)
You are certainly thinking along the right path. Typically, I like to separatte class design from error handling logic. In other words I don't want to have a bunch of $this->error = 'something' logic in the class, as why would you want to add extra code to every class to store/handle/report errors.
Now you get into exceptions vs. errors and when to use each. This is likely a subject for debate, but my personal preference has largely been to throw Exceptions in cases where you get to a point in your code that you cannot recover from or do not have the logic to handle. A great example of this, that I typically use, is throwing Exceptions right at the beginning of any class method that requires parameters of a certain sort or value. Like this example:
public method set_attribute($value) {
if (empty($value)) {
throw new Exception('You must send me something');
} else if (!is_string($value)) {
throw new Exception("You sent me something but it wasn't the string I was expecting.");
}
// method logic here
}
Here if the caller didn't give us a non-empty string, we throw an Exception, as we were not expecting this and we can't guarantee successful completion of the method without a proper value. There is not reason to continue with the method at all. We send the caller the exception with a message about the problem. Hopefully they invoked this method in a try-catch block and can gracefully handle the exception and pass it along up the call stack. If not, your code just stopped execution with fatal error from an uncaught exception (something really easy to catch in testing).
Triggering errors, I honestly use a lot less, and typically use them more for debug, warning purposes. An example of this might be a deprecated method that you still want to work, but you want to give the user an error on
public function old_method() {
trigger_error('This method had been deprecated. You should consider not using it anymore.'. E_USER_WARNING);
// method logic
}
Of course you can trigger whatever level of E_USER class warning here yourself.
Like I said, I tend to work a lot more with Exceptions, as they are also easily extensible for easy use with logging and such. I almost always would have a custom Exception class extending from PHP's base Exception class that also provides logging, etc.
The other thing to consider is global error handling and Exceptoin handling. I strongly recommend using these and having these be some of the very first lines of code in any new project. Again, it will give you much better control over how you log errors/exceptions than what you can get by default.
I don't see a problem with how you are doing it, but If you want to dive into Exceptions, learn how to use try/catch statements. Usually it would be something like this:
try {
//some code that may cause an error here
} catch (Exception e) {
//if a error is found, or an exception is thrown in the try statement, whatever here will execute
//you can get the error message by using e->getMessage()
}
you can read more about it here: http://php.net/manual/en/language.exceptions.php

Categories