PHP : If...Else...Query - php

I am executing this statement under while (($data=fgetcsv($this->fin,5000,";"))!==FALSE)
Now what I want in else loop is to throw exception only for data value which did not satisfy the if condition. Right now am displaying the complete row as I am not sure how to throw exception only for data which does not satisfy the value.
Code
if ((strtotime($data[11]) &&strtotime($data[12])&&strtotime($data[16]))!==FALSE
&& ctype_digit($data[0]) && ctype_alnum($data[1]) && ctype_digit($data[2])
&& ctype_alnum($data[3]) && ctype_alnum($data[4]) && ctype_alnum($data[5])
&& ctype_alnum($data[6]) && ctype_alnum($data[7]) && ctype_alnum($data[8])
&& $this->_is_valid($data[9]) && ctype_digit($data[10]) && ctype_digit($data[13])
&& $this->_is_valid($data[14]))
{
//Some Logic
}
else
{
throw new Exception ("Data {$data[0], $data[1], $data[2], $data[3],
$data[4], $data[5], $data[6], $data[7],
$data[8], $data[9], $data[10], $data[11], $data[12],
$data[13], $data[14], $data[16]} is not in valid format");
}
Guidance would be highly appreciated as to how can I throw exception only for data which did not satisfy the if value.

Why not separate the tests ? i.e. do each test one by one, and throw an exception if a specific test fails ?
Copy-pasting from your code, it would probably look like this :
if (!strtotime($data[11])) {
throw new Exception("field 11 : {$data[11]} is not a valid date");
}
if (!strtotime($data[12])) {
throw new Exception("field 12 : {$data[12]} is not a valid date");
}
// Some more...
if (!ctype_alnum($data[8])) {
throw new Exception("field 8 : {$data[8]} is not a valid alnum");
}
// And so on...
// And when all is tested, you know the items
// in $data are all OK
This way :
You can know which field caused a validation failure
If you have several distinct tests on the same field, you can know which specific test failed
And, as a possibility, you could (if needed) thrown different kind of exceptions, depending on the test that failed (i.e. one kind of exception for dates, one for integers, ...) -- in some cases, that might be useful.
Edit after the comment : more full example
Yes, you can validate field by field, and still work line by line.
You just have to wrap your testing code in a try/catch block, that's inside the loop that goes line by line ; a bit like that :
$validData = array();
$errors = array();
while ($data = fgetcsv($f)) {
try {
// Validate the data of the current line
// And, if valid, insert it into the database
if (!strtotime($data[11])) {
throw new Exception("field 11 : {$data[11]} is not a valid date");
}
if (!strtotime($data[12])) {
throw new Exception("field 12 : {$data[12]} is not a valid date");
}
// Some more...
if (!ctype_alnum($data[8])) {
throw new Exception("field 8 : {$data[8]} is not a valid alnum");
}
// And so on...
// And when all is tested, you know the items
// in $data are all OK
// => which means it can be inserted into the DB
// Or you can just put the valid data into a "temporary" array, that will be used later :
$validData[] = $data;
} catch (Exception $e) {
// An error has occurend on the current line
// You can log it, if necessary :
$errors[] = $e->getMessage();
}
}
// Now that the whole file has been read, test if there's been an error :
if (empty($errors)) {
// No error
// => insert the data that's in $validData
} else {
// There's been an error
// => don't insert the data that's in $validData, if you don't want to insert anything
}
With that :
If there is an exception on one line (i.e. validation fails), you'll jump to the catch block, to deal with the problem
And the loop will then restart, for the next line.
EDIT: (By Yacoby)
Rather than having endless if statments, you could just define which elements should be checked by which function and then process them in a loop. That way it avoids having 16 if statements.
Code example:
foreach ( array(11,12,16) as $index ){
if ( !strtotime($data[$i]) ){
throw new Exception("field {$i} : {$data[$i]} is not a date");
}
}
foreach ( array(1,3,4,5,6,7,8) as $index ){
if ( !ctype_alnum($data[$i]) ){
throw new Exception("field {$i} : {$data[$i]} is not alphanumeric");
}
}
foreach ( array(2, 10) as $i ){
if ( !ctype_digit($data[$i]) ){
throw new Exception("field {$i} : {$data[$i]} is not a valid digit");
}
}
if ( !$this->_is_valid($data[14]) ){
throw new Exception("field {14} : {$data[14]} is not valid");
}

You'll need to break up your massive if statement into one per value.

I think you'd be better off breaking this up into many if statements like
if(!strtotime($data[11])
{
throw new Exception("...");
}
if(!strtotime($data[12]))
{
throw new Exception("...");
}
//after all of your if statements now do business logic
//remember that all of your if conditions have to be met to get this far
//because throwing the exception will leave this stack
//so it functions sort of like the else clause would.

Related

How to check my statement but like individually if it is coded as one

This is a function i am currently using for registering of user account in php.
function checkpost($input, $mandatory, $pattern) {
$inputvalue=$_POST[$input];
if (empty($inputvalue)) {
printmessage("$input field is empty");
if ($mandatory) return false;
else printmessage("but $input is not mandatory");
}
if (strlen($pattern) > 0) { //Checks for Input Validation
$ismatch=preg_match($pattern,$inputvalue);
if (!$ismatch || $ismatch==0) { // If is not match or is match = 0
printmessage("$input field wrong format <br>");
if ($mandatory) return false;
// header("location: registerform.php");
}
}
return true;
}
$checkall=true;
$checkall=$checkall && checkpost("name",true,""); //Mandatory
$checkall=$checkall && checkpost("email",true,"/^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/i");
$checkall=$checkall && checkpost("password",true,"/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$!%*?&])[A-Za-z\d#$!%*?&]{8,}$/");
$checkall=$checkall && checkpost("nric",true,""); //Mandatory
$checkall=$checkall && checkpost("mobile",true,"");
$checkall=$checkall && checkpost("address",true,"");
I tried doing this way of method to check for the statement I have about but I am unsure how can i check like individually like email, password,nric. Is there something wrong with my ifelse cause when I do
// if (!$checkall) { The default error
// printmessage("Error checking inputs<br>Please return to the registration form");
// die();
// }
This will work but I want to check each individual field and print it out. Please help me I'm struggling right now
This is the one I tried but the regex statement suddenly does not work and it will print out the wrong echo statement even if the email format is correct. Seeking help please help me thank you in advance
if (!$checkall=$checkall && checkpost("email",true,"/^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/i")) {
echo "Invalid email";
die();
}
elseif (!$checkall && checkpost("password",true,"")) {
echo "Invalid password";
die();
}
You could reorder your code for some prettier logic by wrapping the validation into a try/catch block. This will validate each entry, but throw an exception on the first error. When one happens the helper variable $hasErrors is set to true. So you know after validation if any one failed or not.
$hasErrors = false;
try {
if (!checkpost("name", true, "")) throw new Exception("Name is missing");
if (!checkpost("email", true, "/^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/i")) throw new Exception("Wrong email format");
if (!checkpost("password", true, "/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$!%*?&])[A-Za-z\d#$!%*?&]{8,}$/")) throw new Exception("Password insecure");
if (!checkpost("nric", true, "")) throw new Exception("Nric?");;
if (!checkpost("mobile", true, "")) throw new Exception("Mobile missing");
if (!checkpost("address", true, "")) throw new Exception("Address missing");
} catch (Exception $e) {
$hasErrors = true;
echo "Error: " . $e->getMessage();
}
if (!$hasErrors) {
echo "Success";
}
Note: You don't need the message for exception at all or print it! I've added it for demonstration purpose.

For each loop continious but doesn't fill array

Problem
Hey, my array $isActiefErr and $naamErr doesn't fill up after I throw an exception, but the foreach loop does continue to validate the values. I know the foreach loop keeps on looping, because the array which should have all the values is filled, but the error array stops after it encounters its first error.
What I have tried:
I've tried to print the array but it only pushes the first error into my array. It then stops validating. This also shows in my error log. I think the problem would be the try/catch, but I simply cannot confirm this, because of my lack of knowledge regarding try/catches.
Question
How can I get the array to push and display all the errors with a try/catch block surrounding it? Or am I simply missing something and isn't the problem related to the try/catch?
This is my code:
$validateOk = 0;
$setVar = new SetVariable();
$teller = 1;
$save = null;
$validateOk = 0;
$con->beginTransaction();
$weg = TypeQuery::create()->find();
$weg->delete();
try {
foreach ($_POST as $key => $value) {
if (isEven($teller)) {
$validateOk += $setVar->nameval($key)
->onerror($isActiefErr[]) //errors aren't being pushed into this array, besides the first one.
->validator(v::numericVal())
->go();
if ($validateOk == 0) {
$save->setCode(substr($key, 1));
$save->setIsActief($value);
$save->save();
} else {
//ROLLBACK/CATCH
throw new Exception($error);
}
} else {
$validateOk += $setVar->nameval($key)
->onerror($naamErr[])
->validator(v::alpha('/()éá&., '))
->go();
if ($validateOk == 0) {
$save = new Type();
$save->setCode(substr($key, 1));
$save->setNaam($value);
} else {
//ROLLBACK/CATCH
throw new Exception($error);
}
}
$teller += 1;
}
$con->commit();
} catch (Exception $e) {
$error = "Het opslaan is fout gegaan!";
} {
$con->rollback();
}

PHP Try catch issue [duplicate]

I have a large mathematical expression that has to be created dynamically. For example, once I have parsed "something" the result will be a string like: "$foo+$bar/$baz";.
So, for calculating the result of that expression I'm using the eval function... something like this:
eval("\$result = $expresion;");
echo "The result is: $result";
The problem here is that sometimes I get errors that says there was a division by zero, and I don't know how to catch that Exception. I have tried things like:
eval("try{\$result = $expresion;}catch(Exception \$e){\$result = 0;}");
echo "The result is: $result";
Or:
try{
eval("\$result = $expresion;");
}
catch(Exception $e){
$result = 0;
}
echo "The result is: $result";
But it does not work. So, how can I avoid that my application crashes when there is a division by zero?
Edit:
First, I want to clarify something: the expression is built dynamically, so I can't just eval if the denominator is zero. So... with regards to the Mark Baker's comment, let me give you an example. My parser could build something like this:
"$foo + $bar * ( $baz / ( $foz - $bak ) )"
The parser build the string step by step without worrying about the value of the vars... so in this case if $foz == $bak there's in fact a division by zero: $baz / ( 0 ).
On the other hand as Pete suggested, I tried:
<?php
$a = 5;
$b = 0;
if(#eval(" try{ \$res = $a/$b; } catch(Exception \$e){}") === FALSE)
$res = 0;
echo "$res\n";
?>
But it does not print anything.
On PHP7 you can use DivisionByZeroError
try {
echo 1/0;
} catch(DivisionByZeroError $e){
echo "got $e";
} catch(ErrorException $e) {
echo "got $e";
}
if ($baz == 0.0) {
echo 'Divisor is 0';
} else {
...
}
Rather than use eval, which is highly dangerous if you're using user-input within the evalled expression, why not use a proper parser such as evalmath on PHPClasses, and which raises a clean exception on divide by zero
You just need to set an error handler to throw an exception in case of errors:
set_error_handler(function () {
throw new Exception('Ach!');
});
try {
$result = 4 / 0;
} catch( Exception $e ){
echo "Divide by zero, I don't fear you!".PHP_EOL;
$result = 0;
}
restore_error_handler();
Here's another solution:
<?php
function e($errno, $errstr, $errfile, $errline) {
print "caught!\n";
}
set_error_handler('e');
eval('echo 1/0;');
See set_error_handler()
As others have mentioned, consider trying a solution that will let you check if the denominator is 0.
Since that advice seems useless your purpose, here's a little background on PHP error handling.
Early versions of PHP didn't have exceptions. Instead, error messages of various levels were raised (Notices, Warnings, Etc). A Fatal error stops execution.
PHP5 brought exceptions to the table, and newer PHP provided libraries (PDO) will throw exceptions when bad/unexpected things happen. Hoever, the core codebase was NOT rewritten to use exception. Core functions and operations still rely on the old error system.
When you divide by 0, you get a Warning, not an exception
PHP Warning: Division by zero in /foo/baz/bar/test.php(2) : eval()'d code on line 1
PHP Stack trace:
PHP 1. {main}() /foo/baz/bar/test.php:0
PHP 2. eval() /foo/baz/bar/test.php:2
If you want to "catch" these, you'll need to set a custom error handler that will detect division by zero errors and do something about them. Unfortunately, custom error handlers are a catch all, which means you'll also need to write some code to do something appropriate with all other errors.
if(#eval("\$result = $expresion;")===FALSE){
$result=0;
}
Won't just catch divide by 0 errors though.
I was facing that problem as well (dynamic expressions). Idid it that way which might not be the nicest way but it works. Instead of throwing an Exception you can of course return null or false or whatever you wish. Hope this helps.
function eval_expression($expression)
{
ob_start();
eval('echo (' . $expression . ');');
$result = ob_get_contents();
ob_end_clean();
if (strpos($result, 'Warning: Division by zero')!==false)
{
throw new Exception('Division by zero');
}
else return (float)$result;
}
I've been struggling with this too, the set_error_handler solutions were not working for me, probably based on PHP version differences.
The solution for me was to attempt to detect an error on shutdown:
// Since set_error_handler doesn't catch Fatal errors, we do this
function shutdown()
{
$lastError = error_get_last();
if (!empty($lastError)) {
$GLOBALS['logger']->debug(null, $lastError);
}
}
register_shutdown_function('shutdown');
I'm not sure why a divide by 0 is shutting down rather than being handled by the set_error_handler but this helped me get beyond it just silently dying.
If no additional handling is necessary you could also just do
$division = $foo / ($bar ?: 1);
Use a # (An error control operator.) This tells php to not output warnings in case of errors.
eval("\$result = #($expresion);");
if ($result == 0) {
// do division by zero handling
} else {
// it's all good
}
A string containing numbers and the mathematical operators + - * / is passed as input.
The program must evaluate the value of the expression (as per BODMAS) and print the output.
Example Input/Output:
If the argument is "7 + 4*5" the output must be 27.
If the argument is "55 + 21 * 11 - 6/0" the output must be "error" (As division by zero is not defined).
Problem:
b=1; c=0;
a=b/c;
// Error Divide by zero
Solution simple:
if(c!=0) a=b/c;
else // error handling
I realize this is an old question, but it is relevant today and I don't really like the answers here.
The proper way to fix this, is by actually evaluating the expression yourself - that is, by parsing the expression, then evaluating it step by step, instead of by transpiling it to PHP. This can be done using the https://en.wikipedia.org/wiki/Shunting-yard_algorithm.
I wrote the following implementation, but I haven't tested it. It's based on the above Wikipedia article. There is no support for right-associative operators, so it's slightly simplified.
// You may need to do a better parsing than this to tokenize your expression.
// In PHP, you could for example use token_get_all()
$formula = explode(' ', 'foo + bar * ( baz / ( foz - bak ) )');;
$queue = array();
$operators = array();
$precedence = array('-' => 2, '+' => 2, '/' => 3, '*' => 3, '^' => 4);
$rightAssoc = array('^');
$variables = array('foo' => $foo, 'bar' => $bar, 'baz' => $baz, 'foz' => $foz, 'bak' => $bak);
foreach($formula as $token) {
if(isset($variables[$token])) {
$queue[] = $variables[$token];
} else if(isset($precedence[$token])) {
// This is an operator
while(
sizeof($operators) > 0 &&
$operators[sizeof($operators)-1] != '(' && (
$precedence[$operators[sizeof($operators)-1]] > $precedence[$token] ||
(
$precedence[$operators[sizeof($operators)-1]] == $precedence[$token] &&
!in_array($operators[sizeof($operators)-1], $rightAssoc)
)
)
) $queue[] = array_pop($operators);
$operators[] = $token;
} else if($token == '(') {
$operators[] = '(';
} else if($token == ')') {
while($operators[sizeof($operators)-1] != '(') {
$queue[] = array_pop($operators);
}
array_pop($operators);
} else if($token == ')') {
while($operators[sizeof($operators)-1] != ')') {
$queue[] = array_pop($operators);
}
if(null === array_pop($operators))
throw new \Exception("Mismatched parentheses");
}
$queue = array_merge($queue, array_reverse($operators));
$stack = array();
foreach($queue as $token) {
if(is_numeric($token)) $stack[] = $token;
else switch($token) {
case '+' :
$stack[] = array_pop($stack) + array_pop($stack);
break;
case '-' :
// Popped variables come in reverse, so...
$stack[] = -array_pop($stack) + array_pop($stack);
break;
case '*' :
$stack[] = array_pop($stack) * array_pop($stack);
break;
case '/' :
$b = array_pop($stack);
$a = array_pop($stack);
if($b == 0)
throw new \Exception("Division by zero");
$stack[] = $a / $b;
break;
}
}
echo "The result from the calculation is ".array_pop($stack)."\n";
In your particular case
Even though I would prefer the Shunting Yard solution - if I still decided to go for an eval()-version, I would create a custom_division($leftHandSide, $rightHandSide) method, that throws an exception. This code:
eval("$foo + $bar * ( $baz / ( $foz - $bak ) )");
becomes
function custom_division($a, $b) { if($b == 0) throw Exception("Div by 0"); }
eval("$foo + $bar * ( custom_division( $baz, ( $foz - $bak ) )");
using intdiv and DivisionByZeroError:
try {
$a = 5;
$b = 0;
intdiv($a,$b);
}
catch(DivisionByZeroError $e){
echo "got {$e->getMessage()}";
}
This is the best way I found to accomplish this:
error_clear_last(); // Clear any previous error
$result = #(1/0); // Executes the division, suppressing the errors
$e = error_get_last(); // Catches the last error
if ($e !== null && $e['message'] == 'Division by zero') {
// Division by zero occurred, do something here
}

Codeigniter Try Catch Transaction

I have this transaction and try catch statement that checks the value of each $_POST['count'] is not less than 0. *the rollback only happens when the if statement is false it doesn't include the past update which is incorrect
$this->db->trans_begin();
foreach($_POST['ID'] as $val => $r)
{
//Gets Count
$this->db->select('count');
$this->db->from('table1');
$this->db->where('table_id', $r);
$oc = $this->db->get()->row('count');
$nc = (($oc) - $_POST['count'][$val]);
//Gets Total
$this->db->select('cost');
$this->db->from('table1');
$this->db->where('table_id', $r);
$ot = $this->db->get()->row('cost');
$total = ($ot + $total);
try{
if($nc > 0){
//Updates Quantity
$process = array(
'current_count' => $nc,
);
$this->db->where('product_id', $rm);
$this->db->update('products', $process);
}
}
catch(Exception $e){
$this->db->trans_rollback();
$this->session->set_flashdata('error','Production Failed. 1 or more Raw Materials required for production is insufficient.');
exit;
}
}
$this->db->trans_commit();
there are insert and update statements afterwards but what i want is to stop the whole process if an exception is caught apparently the exit; statement doesn't do so
There are a several ways to do this. Perhaps the easiest is this.
Model:
//I'm making the function up cause you don't show it
public function do_something(){
//all code the same up to here...
if($nc > 0){
//Updates Count
$process = array('count' => $nc);
$this->db->where('table_id', $r);
$this->db->update('table1', $process);
} else {
$this->db->trans_rollback();
throw new Exception('Model whats_its_name has nothing to process');
}
The catch statement in the model will catch any exception that the database class(es) might throw. (Do they throw any exceptions? I don't know.)
Controller
try{
$this->some_model->do_something();
}
catch (Exception $e) {
//catch the exception thrown in do_something()
//additional handling here
}
All that said, it might be wise to check $_POST['count'] for the appropriate values before you call $this->some_model->do_something();

Why an Exception is not raised in PHP?

$keys = array( "layerName", "lat", "lon", "radius","CHECKBOXLIST");
$value = array();
try {
foreach( $keys as $key ) {
if ( isset($_GET[$key]) )
$value[$key] = $_GET[$key];
else
throw new Exception($key ." parameter is not passed in GetPOI request.");
}//foreach
}
catch(Exception $e) {
echo 'Message: ' .$e->getMessage();
}
This code written is to get values of the parameters from GET requests. If Any of these parameters is not passed in GET request, it should raise an exception. but in this case, it doesnot. What could be the problem?
$_GET[$key] is probably set but has no value, so it will assign an empty string value to $value[$key] instead of throwing a new exception. I would rewrite your if statement to check for empty value instead.
if ( isset($_GET[$key]) === true && empty($_GET[$key]) === false )
{
$value[$key] = $_GET[$key];
}
elseif ( isset($_GET[$key]) === true && empty($_GET[$key]) === true)
{
throw new Exception($key ." parameter is not passed in GetPOI request.");
break;
}
Try adding a break after throwing the exception. Like this:
if ( isset($_GET[$key]) )
$value[$key] = $_GET[$key];
else{
throw new Exception($key ." parameter is not passed in GetPOI request.");
break;
}
--EDIT--
I have to quickly add that i tried running your code and raised an exception as expected.

Categories