while using Codacy to analyze my PHP code I found a number of errors caused by the exit(); function. here's one function,
public function saveCssForm(){
$data = $_POST;
if(!$data){
// is a direct acess
$this->index();exit();
}
// update the data
$this->csssettingmodel->updateCSS($data);
// save the notifications
$this->notify_update($data['site_id'],$data['lang_key']);
// set the success message
$this->session->set_flashdata('edit_item', 'edited');
// redirect to the view page
$baseUrl = $this->config->item('base_url');
redirect($baseUrl.'index.php/cssSettings/view/'.$this->session->userdata("languageabbr"));
}
public function index()
{
// Denay Direct Access
echo "<hr><h1><center>NO DIRECT ACCESS</h1> </center>";
echo "<center>You are not permitted to access this page </center>";
}
and the codacy result shows this...
any alternatives or suggestions to avoid this would be helpful.
Codacy is not displaying errors, in the sense of problems you need to fix; it is analysing the quality of your code, and suggesting that the exit appearing in this position is not a good practice, so you might want to fix it.
Firstly, application frameworks are often designed to have a single point of entry, process some logic, and then return a result to the entry point which will output and clean up. Exiting from different points in the code makes it harder to predict the flow, because whole sections of the code may look reachable but actually come after the program has exited.
Secondly, such code might be used for debugging, to interrupt the flow of execution at a particular point to display some intermediate data or simulate a particular failure. In this case, it appearing in the analysed code would suggest that you had left the debugging code in accidentally.
Related
im developing my PHP framework and at the moment im stuck with a strange behaviour in my error-dispatching page.
The page itself is beautiful, it catches and lists all error using a custom error-handler registered with "set_error_handler()" and can print the line, file, invoked variables and such. It even triggers multiple errors perfectly (except for fatal or syntax-errors which causes the script to hold) but still the dispatches the fatal or even syntax error in this case and even shows me, even when its a null-pointer in a template where the error is located which is beautiful and works awesome.
This system works "using set_error_handler"! The entire output (rendering html /php templates) is realised using "ob_start" and "ob_get_clean" - outputbuffer context.
Next I check if the error-handler catched any errors (will be written in an array in the error-handler's class) and if there are errors and error-display is enabled (developer mode = on) the error-dispatcher page will be displayed instead of the page's content.
However since I implemented that I have one strange behaviour which I do not want:
Whenever I use die() inside of outputbuffer context ((ob_start() ... ob_get_clean()) ) The registered error-handler method is called with an empty error-list displayed and even error_get_last() is empty, but still he triggers that damn function.
This is very disturbing as you cant use die to hold the script to test the output of certain variables which is disturbing in development and seems to be an unusual behaviour to me.
I think posting my entire code is making the thing a little bit too complicated for you to understand thatswhy I leave a little draft explaining the situation, its basically same as it looks in my classes:
//index.php
$errorList = array();
function myErrorHandler($errorType, $errorString, $errorFile, $errorLine, array $errorContext) {
global $errorList;
$errorList[] = $errorString;
}
set_error_handler("myErrorHandler");
//Here my classses and entire rest of framework is loaded...()
//Initialise output
$output = "";
//This method parses templates, it remotely close works like that...
function includeTemplate($templatePath) {
global $output;
ob_start("myErrorHandler");
include($templatePath);
$output .= ob_get_clean(); //Attach to output
}
//This method is called at the very end, it flushes the output, wether by displaying error-dispatcher or page content to be shown.
function flush() {
global $output;
if(count($errorList) > 0) {
echo implode("<br />", $errorList);
} else {
echo $output;
}
}
//Template file: registerTemplate.php
<div class="container">
<Some template output here, doesnt matter if an error occured...>
<?php die($var); ?> //<- Error rised -> Entering "myErrorHandler()" -> but why????
</div>
-> This die() above would rise an error because registerTemplate.php was somewhen parsed using includeTemplate("reigsterTemplate"); which is as located within an ob_start() context. It does not matter if an error occured before or not or even if I just place die("!"); without any invoked variable, it will riase an error.
If I put the die() before or after the include_template context, in upper scope it works as usual and the error_handler does not trigger, as it should work.
Can anyone tell me why this is happening? Thanks alot!
(Important: again this code is not realistic I know its just a draft from how the things look like very barely, dont bother with that giving me hints that this is a bad way to do things. The entire thing is perfectly object oriented and very well structured. I just made this little draft to make you guys understand in what order the methods are called and how my problem comes up because posting my code would waste me and you alot of time as it would be too huge and complex here).
I'm creating various 'my version' of web services. Basically, it's a yii controller with lots of actions.. each action is as follow
public function actionNameOfWebService()
{
if(isset($_POST))
{
// do some processing, when I have a result... I do ..
print CJSON::encode('result.');
}
else
{
print CJSON::encode('only post methods allowed');
}
}
Lots of those actions are in one particular controller. Everything's working fine..before I go to production, do I need to add a 'die;' statement after every print CJSON::encode statement.
Since you are using Yii, you should simply use :
Yii::app()->end();
http://www.yiiframework.com/doc/api/1.1/CApplication#end-detail
No. You don't absolutely need die or exit. I would argue that using it is a bit of anti-pattern. It breaks encapsulation.
If you have some kind of output buffering set up the die might actually be bad. If you're proxying a request die will kill the whole process etc. There are more scenarios like this.
You definitely should use Yii::app()->end();This is because if you have any debugging output, or profiling output, this will also be included in the response unless you tell the app to finish. Your validation could break if you fail to include this.
You don't have to but when you add it, you'll be sure that nothing will be printed after JSON, which will break parsers attempts to read that data.
But if you know that there is nothing more, you can skip it.
HTML HEADER CODE HERE
<div id="content">
<?php
$checkvars = array('subject','message');
foreach ($checkvars AS $checkvar) if (strpos($_REQUEST[$checkvar],'{php}')!==false) die("We are sorry, but you cannot use \"{php}\" in a ticket submission. If you do have a legitimate issue, please press the back
button in your browser and then change any instances of \"{php}\" to \"(php)\" so that your ticket may be submitted. Keep in mind that in the event that you are trying to exploit our system, we log and report all hack attempts to IC3.GOV.");
?>
</div>
HTML FOOTER CODE HERE
I am using the above code for a billing system to stop the exploit of eval through support ticket submissions. The header is working fine, but the footer will not show up (because of the die command i assume). I have very little knowledge of coding (I didn't write the above code, it was wrote by someone else that shared it on another website) and was hoping someone could help me get my footer to appear.
Create your own function like this
died($message)
{
//call footer
die($message)
}
//Use it like this
died('You did something wrong');
YOU CANT!
You asked the script to die right now - so how are you supposed to output code after that
[Sounds like the CS issues I got many years ago when a customer complained their database was closed badly after the machine lost power - because only I can write that special code that runs when the machine is off to neatly close the tables]
Doing any serious work "inside" the HTML is a bad structure to begin with. Do all your validation, database queries, file operations and so on before you begin any output of any sort.
<?php
// check $_POST
// update the database
// validate data
// water the plants
// DECIDE WHAT THE USER SHOULD SEE
?>
<html>
...
</html>
If you detect any error or invalid action, you can simply output a complete error page. An architecture that emphasizes this a lot is MVC, where controller logic and views are clearly separated. Try to learn from that structure.
You can use register_shutdown_function to define a function that will run when die() is called before the script dies.
Alternatively, you could just replace the die()s in your code above with a function that calls die() at the end.
IC3.gov is the reason Advanced Currency Markets got shut down in Switzerland.
I am using Cakephp but this is a MVC/php doubt
letting the view display the message
vs
echo 'Invalid Data'; exit;
I would like to know is there any pitfalls in the second case like memory leak etc.. Which one is better
EDIT
In case of a ajax call is exit good. and what about memory leak and other issues . Are all variables deallocated
You should use a custom ExceptionHandler (set_error_handler / set_exception_handler) and throw an Exception if you encounter any errors (CakePHP should already provide an ExceptionHandler). Make some space in your view and if the ExceptionHandler/ErrorHandler has a message, show it there to let the user know.
Your second code will just produce a blank page containing the little text. Every user will appreciate if you show the message inside your usual page layout instead of producing a blank page (which looks broken to most people).
The Cake tools to signal errors to the user are session messages and error views.
For "passive" actions like view actions, you should throw a 404 or similar, possibly more specialized error, e.g. if the requested model does not exist:
function view($id) {
$data = $this->Model->read(null, $id);
if (!$data) {
$this->cakeError('error404');
}
...
}
See Error Handling with CakePHP.
For any POST action, you should return the user to the view and display an error message using $this->Session->setFlash('Error!') and appropriate error messages for each invalid form field. That's the default behavior of baked views and controllers.
Terminating the whole script with exit makes for a miserable user experience.
In general, you should avoid exit. Exit is an abnormal termination, and programs should not terminate abnormally. Even if an error occurs, there are still many things that needs to be done - cleanup, logging, notifying the user etc. After all, your operating system doesn't reboot every time it cannot open a file.
performance-wise (AJAX cals)
Use exit().
user experience-wise (standard site nav)
Show the error in a proper formated page keeping the user within your site.
I created a few mediawiki custom tags, using the guide found here
http://www.mediawiki.org/wiki/Manual:Tag_extensions
I will post my code below, but the problem is after it hits the first custom tag in the page, it calls it, and prints the response, but does not get anything that comes after it in the wikitext. It seems it just stops parsing the page.
Any Ideas?
if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) {
$wgHooks['ParserFirstCallInit'][] = 'tagregister';
} else { // Otherwise do things the old fashioned way
$wgExtensionFunctions[] = 'tagregister';
}
function tagregister(){
global $wgParser;
$wgParser->setHook('tag1','tag1func');
$wgParser->setHook('tag2','tag2func');
return true;
}
function tag1func($input,$params)
{
return "It called me";
}
function tag2func($input,$params)
{
return "It called me -- 2";
}
Update: #George Mauer -- I have seen that as well, but this does not stop the page from rendering, just the Mediawiki engine from parsing the rest of the wikitext. Its as if hitting the custom function is signaling mediawiki that processing is done. I am in the process of diving into the rabbit hole but was hoping someone else has seen this behavior.
Never used Mediawiki but that sort of problem in my experience is indicative of a PHP error that occurred but was suppressed either with the # operator or because PHP error output to screen is turned off.
I hate to resort to this debugging method but when absolutely and utterly frustrated in PHP I will just start putting echo statements every few lines (always with a marker so I remember to remove them later), to figure out exactly where the error is coming from. Eventually, you'll get to the bottom of the rabbit hole and figure out exactly what the problematic line of code is.
Silly me.
Had to close the tags.
Instead of<tag1> I had to change it to <tag1 /> or <tag1></tag1>
Now all works!