I'm working with the PHP Slim Framework in the version 2.6.1 (due to some limitation to upgrade PHP no a newer version) and when trying to use flash messages inside of a try/catch block the messages are not stored in the session when the template is rendered.
For example, the code below works fine (when the validator get some error the page is redirected with the desired flash messages):
$objValidation = FormValidator::isValidData($post);
if($objValidation->bolHasError)
{
$app->flash('objValidation', serialize($objValidation));
$app->flash('selectedData', $post);
return $app->redirect('/app/edit/form/components/');
}
But if I start using a try block, like below, then the flash message is not stored in the $_SESSION (or even in the {{ flash }} in templates):
try {
$objValidation = FormValidator::isValidData($post);
if($objValidation->bolHasError)
{
$app->flash('objValidation', serialize($objValidation));
$app->flash('selectedData', $post);
return $app->redirect('/app/edit/form/components/');
}
# some other stuff processed here...
}
catch(Exception $e) {
# do something
}
P.S.: the sessions are stored in the PHP native way ( session_start() ).
There are any limitations of scope for using the flash messages in that way?
I've figured out that the try block create a "isolated scope". So, I tried to to put a return false before the redirect to test if the in next page the flash message would show up. And finally the flash message was stored in the $_SESSION variable (of course the redirection was not executed, but at least I've discovered that the issue is related with the try scope).
Then, the solution I found was to raise an exception and do the redirect inside the catch block. Like this:
$objValidation = FormValidator::isValidData($post);
if($objValidation->bolHasError)
{
throw new Exception('validation_error');
}
and then capture the error into the catch block:
catch(Exception $e)
{
if($e->getMessage() == 'validation_error')
{
$app->flash('objValidation', serialize($objValidation));
$app->flash('formData', $post);
return $app->redirect('/api/form/change/components/');
}
}
In that way I was able to get the flash message into template.
Related
This a php application running on Google App Engine. I'm using getImageServingUrl to get a url and store it for later use. I've actually implemented this in another part of the application, but in this case, when run, the php code stops right at the point where I make the call to get the url. The are no errors in the page or in the App Engine log. Is there another place to get errors? I'm not having luck tracking down the issue. Here's what I have:
// At the top of the page I call this
use google\appengine\api\cloud_storage\CloudStorageTools;
// Some processing takes place to get the storage location of the image then
if (is_file($full_path_photo)) {
echo 'Getting URL...<br>';
$object_public_url = CloudStorageTools::getImageServingUrl($full_path_photo, ['secure_url' => true]);
echo 'Successful<br>';
};
// I've also tried it like this:
$object_public_url = CloudStorageTools::getImageServingUrl($full_path_photo);
// And adding this before the call:
CloudStorageTools::deleteImageServingUrl($full_path_photo);
When I run this, I get the "Getting URL...", then nothing. The page just stops executing.
Try/Catch was able to get an error message for this one. In my case it was kind of a generic error. For the overall issue I think has something to do with my buckets. I tried the whole thing with a different bucket and it seems to work. Here is the example -
// At the top of the page I call this
use google\appengine\api\cloud_storage\CloudStorageTools;
// Some processing takes place to get the storage location of the image in GCP storage then
if (is_file($full_path_photo)) {
try {
$object_public_url = CloudStorageTools::getImageServingUrl($full_path_photo, ['secure_url' => true]);
throw new Exception();
} catch (Exception $e) {
echo 'Error: '.$e->getMessage().'<br>';
};
Thanks for the help Tom.
I'm using CodeIgniter and am trying to execute code in a try/catch block with the idea that errors will stop execution of the code after the error until the catch block is reached, as you would normally think it would work.
However on encountering PHP Errors, the code is continuing. This is causing a database transaction complete command to execute which is .... very bad if there's an error and all of the instructions weren't carried out properly. For example, I have this code which is executed in an ajax request:
// start transaction
$this->db->trans_start();
try {
$this->M_debug->fblog("firstName=" . $triggerOpts->{'firstXXXName'});
$data = array("test_col" => 123);
$this->db->where("id", 4);
$this->db->update("my_table", $data);
// if got this far, process is ok
$status = "process_ok";
// complete transaction
$this->db->trans_complete();
} catch (Exception $ex) {
// output the error
$this->M_debug->logError($ex);
}
In this code, I'm trying to execute a database update as part of a transaction.
My call to $this->M_debug->fblog() is designed to just log a variable to PHP Console, and I've deliberately tried to log a variable that does not exist.
This causes a PHP error, which I guess is a fatal error, and the desired result is that the code after the log commands fails, and the transaction does not complete. However after this error, despite reporting the PHP error in Chrome console, the code keeps right on executing, the database is updated and the transaction is completed. Would appreciate any help in how i could stop this from happening.
Thanks very much, G
EDIT --
As requested heres fblog(), it's simply a Chrome console log request of a variable
public function fblog( $var ) {
ChromePhp::log( $var );
}
Assuming you're using PHP 7.0 or higher, you can catch PHP errors as well as exceptions, however you need to catch Error or the parent Throwable type rather than Exception.
try {
...
} catch (Throwable $ex) {
//this will catch anything, including Errors and Exceptions
}
or catch them separately if you want to do something different for each of them...
try {
...
} catch (Exception $ex) {
//this will catch Exceptions but not errors.
} catch (Error $ex) {
//this will Errors only
}
Note that if you're still only PHP 5.x, the above won't work; you can't catch PHP errors in older PHP versions.
1) I have a view (a neseted one) that triggers a notice-level error
2) I have set up a custom error handler, which is called. Code goes below
3) I want visitor seeing only the "error happened" string in his browser, instead, he sees the half-baked page with this error message appended
4) messing with php's native ob_end_clean only made me clear the contents of the deepest view involved, yet the higher-level views are still half-shown
5) the contents of final_output var of CI_Ouput class is empty string at the moment of error. That's strange is CI is said to pre-buffer everything befoew outputting to the client.
essentially, what I need seems to be discarding any content having been collected so far and replacing it with error message only.
how can I do it?
the code of the handler:
function _error_handler($errno, $errstr) {
echo "error happened";
die();
}
Try to use a Try Catch system?
Try{
//Do something
} catch(Exception $e){
echo "Error has occured!";
}
as suggested in the discussion this had to be related to php's native output buffering wich we can control with ob_* family of functions. Buffering in php can be nested, and CI seems to use it, opening a buffer for each view being loaded.
If we load a view from inside a view, the nesting gets deeper, and generally, when an error occures in the view we don't know how deep we are.
So that's what seems to solve the problem (the code of error handler):
function _error_handler($errno, $errstr) {
$currentLevel=ob_get_level();
for($i=0; $i<$currentLevel-1; $i++) {
ob_end_clean();
}
print "errorrrr!";
die();
}
so it detects how deep it is and cleans as many buffers as needed. After all, we end up with "errorrrr" message being the only thing on the page.
i call an php pgm per cronjob at different times.
the pgm includes many php-files.
each file sends or gets data from partners.
How can i handle errors in one includes pgm.
at the time, one ftp-connection in an included pgm fails so the complete script crushes.
how can i handle this ?
You should wrap code, which is possible to crash, into try/catch construction. This will throw exeption, but the script will continue to work. More here.
Need to know more about you code inorder to give you definite answer.
In general php errors isn't catchable unless you define your own error handler from which you throw exceptions your self. Using the code below makes most runtime errors catchable (as long as they arent considered fatal)
error_reporing(E_ALL);
set_error_handler(function($errno, $errstr, $errfile, $errline) {
if($errno == E_STRICT || $errno == E_DEPRECATED) {
return true;
}
throw new RuntimeException('Triggered error (code '.$errno.') with message "'.$errstr.'"');
});
Btw, You could also define your own exception handler to display triggered errors with a full stack trace when an exception isn't catched.
Notice! I would not suggest that you add this code to a production website without rigorous testing first, making sure everything still works as expected.
Edit:
I have no idea what your code looks like, but I guess you can do something like:
require 'error-handler.php'; // where you have your error handler (the code seen above)
$files_to_include = array(
'some-file.php',
'some-other-file.php',
...
);
foreach($files_to_include as $file) {
try {
include $file;
}
catch(Exception $e) {
echo "$file failed\nMessage: ".$e->getMessage()."\nTrace:\n".$e->getTraceAsString();
}
}
Note: I am using output buffering. It's just wrapped in the head() and foot() functions.
I create pages in my current PHP project by using the following template:
<?php
include 'bootstrap.php';
head();
?>
<!-- Page content here -->
<?php
foot();
?>
Is the following example an appropriate use of die()? Also, what sort of problems might this cause for me, if any?
<?php
include 'bootstrap.php';
head();
try
{
//Simulate throwing an exception from some class
throw new Exception('Something went wrong!');
}
catch(Exception $e)
{
?>
<p>Please fix the following error:</p>
<p><?php echo $e->getMessage(); ?></p>
<?php
foot();
die();
}
//If no exception is thrown above, continue script
doSomething();
doSomeOtherThing();
foot();
?>
Basically, I have a script with multiple tasks on it and I am trying to set up a graceful way to notify the user of input errors while preventing the remaining portion of the script from executing.
Thanks!
I'd do this:
head();
try {
somethingPossiblyWithError();
somethingElse();
} catch (Exception $e) {
handleError();
}
foot();
No deaths necessary. If an error is raised in somethingPossiblyWithError, then somethingElse will get skipped. foot will get executed in both cases.
UPDATE: I upvoted Col. Shrapnel's answer, since I guess you did not think about that, and that is a valuable piece of knowledge. In PHP, you can get an equivalent functionality by output buffering, without explicitly passing values around, but it's not as pretty - however, it works if you are calling functions which will print things and not return them as values, so sometimes it's useful to know.
The whole page structure is wrong.
Though it's most widespread newbie mistake.
One should never output a thing before having all data ready.
Your script may send some HTTP headers, may set up some variables for use in the header() or anything.
Therefore, template use is necessary.
You have to divide your script into 2 parts - getting data part and displaying data part.
So, you have to move header() function much lower.
And based on the Amadan's answer it could be
<?php
include 'bootstrap.php';
try {
getData();
} catch (Exception $e) {
handleError();
}
head();
body();
foot();
?>
handleError() function may set appropriate HTTP error code (404 or 500) and substitute body template with error message text.
Your approach is not recommended for many reasons. You should:
separate the presentation and the logic (take a look at MVC pattern)
avoid procedural code, write object oriented PHP
separate user and admin experience (handle errors gently)
Example, implementing above:
<? $page->debug = true; ?>
<?= $page->getHead(); ?>
<?= $page->getBody(); ?>
<?= $page->getFoot(); ?>
class page {
public debug;
public function getBody() {
try {
//
} catch (Exception $e) {
$this->_errorhandler('message');
}
}
protected function _errorhandler($message) {
if ($this->debug) {
// display error message
} else {
// display nothing, log the error
// or throw concrete exception
// or redirect
}
}
...
}
This is not recommended too (there are many separate classes needed for each task), but you see the point: separating, not mixing everything.