PHP: Run Functions Only After Checking Variable After Each - php

I have a series of functions that I'd like to run. At the end of each function, it either sets a variable TRUE or FALSE. What I'd like to do is break the series if the variable sets to TRUE.
For example. I have the following:
$done = false;
step1(); // Sets $done to false
step2(); // Sets $done to false
step3(); // Sets $done to true
step4(); // Because step3() set $done to true, I wan't step4() to NOT run.
Of course if step3() returns false, I'd like to keep going and run step4().
I know I'll need to use a while, switch, and/or a break. I'm just unclear on how to set this up.
Much appreciated.

It's not much clear to me, but if your functions return booleans, you can try:
step1() || step2() || step3() || step4();
The operator || only evaluate the second operand if the first is false.

it can be done by using a simple if statement if you want.
$done = false;
$done = step1(); // each function returns true or false
if (!$done)
{
$done = step2();
}
if (!$done)
{
$done = step3();
}
if (!$done)
{
$done = step4();
}
correct me if there is any mistakes.

$done = false;
function step1($done){
if($done===false){
//proceed step 2
}
else{
return;
}
}
function step2($done){
if($done===false){
//proceed step 3
}
else{
return;
}
}
function step3($done){
if($done===false){
//proceed step 4
}
else{
return;
}
}
function step4($done){
if($done===false){
//finish
}
else{
return;
}
}

Your question is not very straight forward, probably similar to the form you have so far.
You could create an array with callbacks of your functions and consume them while $done is false and there are still functions to consume:
$doFunctions = ['step1', 'step2', ... , 'stepN'];
$done = false;
while (!$done && $doFunctions)
{
$function = array_shift($doFunctions);
call_user_func($function);
}
As this shows, no switch and no break needed, because you have a simple condition here.
Another alternative would be to "make" the functions return something by wrapping it inside a closure and keep the $done as a reference (context), then return it:
$done = false;
$call = function ($function) use (&$done) {
$function();
return $done;
}
$call('step1')
|| $call('step2')
|| $call('step3')
|| $call('step4')
;
It depends a bit of what you actually need to achieve.

So perhaps my question was misunderstood, but after a while I realized that a try/catch block with exceptions was exactly what I was after. Here is roughly what I ended up doing.
First I set up my functions to throw exceptions on errors.
function step1() {
// do awesome stuff
if ($errorInStep1) {
throw new Exception('There was an error in step 1.');
}
}
function step2() {
// do awesome stuff
if ($errorInStep2) {
throw new Exception('There was an error in step 2.');
}
}
function step3() {
// do awesome stuff
if ($errorInStep3) {
throw new Exception('There was an error in step 3.');
}
}
function step4() {
// do awesome stuff
if ($errorInStep4) {
throw new Exception('There was an error in step 4.');
}
}
So now if there is an error in each of the functions, the script will throw an exception.
Then I wrap those functions in a try/catch block. The script will try to go through each statement, and if something throws and exception...it will stop right there. Perfect.
try {
step1();
step2();
step3();
step4();
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}

Related

Where/When we should use return false in php [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I did a lot of search but couldn't find any clear guide. Please one of you experts answer my question.
Where/when we should use "return false" in an array or an if statement.
for example :
if(file_exists($p)) {
// do something
} else {
echo $error;
return FALSE;
}
whole code:
class Base {
function __construct() {
$url = $_GET['url'];
$url = explode('/',$url);
$p = $url[0].'.php';
if(file_exists($p)) {
require($p);
} else {
require('error.php');
$error = new error();
$error->Not_Exist();
return FALSE;
}
}
Please someone explain me the reasons for use of return false.
Firstly, it only makes sense to return a value if it is potentially going to be used. You can return whatever you want, even if it is not going to be used, but what would be the point?
This makes sense:
function isOfAge($age) {
if ($age >= 18) {
return true;
}
return false;
// Shorter:
// return $age >= 18;
}
This does not make much sense:
function outputName($name) {
echo "Your name is {$name}!";
return true;
}
Secondly, boolean values should only be returned if the result of a function is boolean in nature, such as functions that:
Evaluate or compare values (e.g. isOfAge($age), containsCharacter($str, $char), canBeExecuted($pathToExe), validDate($date), sameValues($a, $b), etc.)
Execute or run something and report back the result (e.g. executeSQL($sql), generateImage($data), runBackgroundProcess($str), etc.)
You can also return a boolean value only if a function fails (or succeeds), such as:
function createName($first, $second) {
if (strlen($first) === 0 || strlen($second) === 0) {
return false;
}
return "{$first} {$second}";
}
And then you can use the return value to check if it worked, and if it did then you can be sure that it contains a string:
$name = createName("Sverri");
if ($name === false) {
die("Invalid first or second name!");
} else {
echo "Hello $name!";
}
That function could also be written using exceptions. Exceptions allow you to stop the script, throw an error, catch that error, and then continue the script:
function createName($first, $second) {
if (strlen($first) === 0) {
throw new \Exception("Invalid first name");
}
if (strlen($second) === 0) {
throw new \Exception("Invalid second name");
}
return "{$first} {$second}";
}
try {
echo createName("Sverri");
} catch (\Exception $e) {
die($e->getMessage());
}
A good rule of thumb is to ask yourself if it makes sense to return a boolean value, and if the returned value is going to be used.
In the code in your question it would not make sense to return any value. You cannot return anything in a constructor anyway, so returning something does not make sense.
If you want to terminate a function without a return value you can just do so:
function uselessFunction() {
return;
}
It will actually return a value, null, but when you just want to terminate a function without returning any particular value then that is how you would do it.
I personally normally use them in functions to tell me if something is happening.
<?php
function isUsernameAvailable($username)
{
// Some db functions.
if ($db->rowCount() == 1) return false;
return true;
}
?>
So if the provided username does not exist in the database then it will return true otherwise it will return false.
Usage,
if (isUsernameAvailable("test") == false) {
// Username does not exist.
} else {
// Username exists.
}

How to return errors from PHP method?

I have a save method in my User class.
If the save method encounters validation errors it returns an array of errors that I display to the user. However this means in my code I have to write:
if (!$user->save()) {
//display success to user
}
Surely my save method should return true on success. But how do I handle errors in that case?
Use try ... catch syntax.
For example:
try {
$user->save();
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
http://php.net/manual/en/language.exceptions.php
I would throw an exception in the event that save() runs into any problems.
If you want to provide an array of validation errors, your could subclass Exception and provide a mechanism for storing the validation errors.
A custom Exception subclass will also help you differentiate between exceptions your code throws explicitly (which you'd like to catch) and exceptions that you didn't expect (which should be fatal).
Here's the subclass:
class UserException extends Exception
{
private $userMessages;
public function __construct($message = "", $code = 0, Exception $previous = null, array $userMessages = null)
{
parent::__construct($message, $code, $previous);
if ($userMessages === null) {
$this->userMessages = array();
} else {
$this->userMessages = $userMessages;
}
}
public function getUserMessages()
{
return $this->userMessages;
}
}
Here's a silly version of a User class that always throws an Exception on save().
class User
{
public function save()
{
$userMessages = array(
'Your password is wrong',
'Your username is silly',
'Your favorite color is ugly'
);
throw new UserException('User Errors', 0 , null, $userMessages);
}
}
To use it:
$user = new User();
try {
$user->save();
} catch (UserException $e) {
foreach ($e->getUserMessages() as $message) {
print $message . "\n";
}
}
You could also accomplish something like this by populating the Exception's $message with, say a semi-colon-delimited list of messages. You could even build a list of constants for error types, then combine them as a bitmask and use that for the Exception's $code. The advantage of these options is you would be using the built in members and not adding anything extra.
More on exceptions:
http://php.net/manual/en/language.exceptions.php
A (bad?) habit I picked up after playing a good bit with erlang is to return tuple values (as a php array).
function my_func() {
$success = true;
$errors = array();
if ( something_fails() ) {
$success = false;
$errors[] = 'something failed..';
}
return array( $success, $errors );
}
list($success, $errors) = my_func();
if ( ! $success ) {
do_somthing_with( $errors );
}
In my experience, this has been really handy when the wild modify legacy code tickets appear and you don't really dare modify anything but could more easily add more legacy to it.
Cheers -
Return either true, or the error array.
And when you check for it, use this:
if ($user->save()===true) {
// display success to user
} else {
// display error to user
}
the === operator performs a typesafe comparison, meaning that it not only checks if the value is true, but also if the type is a boolean. If the array is being returned it's handled as false.
Would be good to return array from validation function like this
$result['ACK'] = 'true';
$result['message'] = 'Success validation'];
on failure
$result['ACK'] = 'false';
$result['message'] = 'validation error message';
Now you can use this array in front end like this
if ($result['ACK']) {
//No Error
} else {
echo $result['message'];
}
Change your condition to, If true then success else return array of errors.
if ($user->save() === true) {
//display success to user
}

Nested if, not exiting - create a function to call functions

I have the following code to validate form data. I have created functions to validate various groups, and then have an if isset statement to check if these functions return true. I have tried many different ways to get this to work.
The problem I am having is this. I want the if isset to end if returning FALSE; but it doesn't, it keeps going and pops up the next alert (in my code I have many functions). How can I get it to exit after the first return FALSE? Do I need to make the isset into a function? So it can exit on return FALSE. thanks
I am having trouble writing a function to call functions in php.
function namecheck ($fname, $lname)
{
$regexp ="/^[A-Za-z]+$/";
//filter through names
if (preg_match($regexp,$fname,$lname))
{
return TRUE;
}
else
{
echo'<script type="text/javascript">alert("Enter your names.")</script>';
return FALSE;
}
}
function emailcheck ($email1, $email2)
{
$regexp="/^[a-zA-A-Z0-9_.]+#[a-zA-Z0-9-]+\.[a-zA-Z0-9.-]+$/";
//validate email address
if (preg_match($regexp,$email1,$email2))
{
return TRUE;
}
else
{
echo '<script type="text/javascript">alert ("Enter a valid email address.")</script>';
return FALSE;
}
}
$fname=$_POST['fname'];
$lname=$_POST['lname'];
$namecheck=namecheck($fname,$lname);
$email1=$_POST['email1'];
$email2=$_POST['email2'];
$emailcheck=emailcheck($email1,$email2);
if (isset($_POST['submit']))
{
if ($namecheck !==TRUE)
{
return FALSE;
}
elseif ($emailcheck!==TRUE)
{
return FALSE;
} //and so on..
else
{
return TRUE;
}
}
A general structure for your functions you could follow is something like this:
function validateName($name) {
// Do Validation. Return true or false.
}
function validateEmail($email) {
// Do Validation. Return true or false.
}
function isFormValid()
{
// Name Validation
if( ! validateName( $_POST['name'] ) )
return false;
// Email Validation
if( ! validateEmail( $_POST['email'] ) )
return false;
// Form is valid if it reached this far.
return true;
}
// In your regular code on Form Submit
if( isset($_POST['submit']) )
{
if( isFormValid() ) {
// Save Form Data to DB
} else {
// Show Some Errors
}
}
That general structure should work fine for you. It could be made a LOT better but, for the sake of learning, this is sufficient.
If you want the script to, as you put, "exit" then you need to use exit(); Generally this is bad as the script will completely stop executing. Maybe you can look into using "break;" to get you out of a loop and stop executing functions within that loop. Another problem is that you are echoing out HTML code in your function which gets executed on assignment and so you will always get an alert generated when it evaluates to FALSE.
edit:
within your if(isset()) block. Inside here you can do{}while(false); which is a loop and will let you break out of it at anytime and prevent further execution of code within that loop.
If a function isn't returning false, then it never reached a return FALSE; statement. It's as simple as that. So let's examine the relevant code:
if (isset($_POST['submit']))
{
if ($namecheck !==TRUE)
{
return FALSE;
}
elseif ($emailcheck !== TRUE)
{
return FALSE;
} //and so on..
else
{
return TRUE;
}
}
So, if $_POST['submit'] is set and is not null, the if block will be reached. Then, if $namecheck is not true OR $emailcheck is not true, the function will return FALSE. You can simplify the above code to just:
if (isset($_POST['submit']))
{
return !(!$namecheck || !$emailcheck);
}
However, it doesn't look like this code is inside a function, so the return statement will do nothing. You have to put it in a function if you want it to work like a function.
Beyond that, I can't help you. I don't know what you want to do with this code. You seem to know how to use and call functions, so I'm not sure what the problem is. If you want to return from a function, put code in a function and call return. Right now your code is not in a function, so return won't do anything.

Code doesn't make sense -- two conditionals within PHP try

I have inherited an application that is not doing what it's supposed to do. I have isolated the problem to the database not being properly attached. The programmer wrote this function that seemingly is suppose to evaluate whether the database is attached, calling the "attachPaymentDatabase()" function to attach it if it's not.
function attachPaymentDatabaseIfNotDoneAlready()
{
global $db;
global $hasPaymentDatabaseAttached;
// Determine if we have attached the payment tables, and if not, add them.
$hasPaymentDatabaseAttached = false;
try {
// this new way should work the best-- looking for PAY.
$alldb = queryall($db, "PRAGMA database_list;");
for ($i = 0; $i < count($alldb); $i++)
{
$alldb[$i] = array_change_key_case($alldb[$i], CASE_LOWER);
if (strtolower($alldb[$i]['name']) == 'pay')
{
debugEmail("condition 1 worked.");
$hasPaymentDatabaseAttached = true;
break;
}
}
// if its name changed this will also work
if (!$hasPaymentDatabaseAttached)
{
$r = #$db->querySingle("SELECT * FROM PAY_PARAMETER;");
$hasPaymentDatabaseAttached = true;
debugEmail("condition 2 worked.");
}
}
catch(Exception $e)
{
}
if (!$hasPaymentDatabaseAttached)
{
debugEmail("nothing worked.");
attachPaymentDatabase();
}
}
I have written a debugEmail() function that emails me a defined message with a timestamp as used above. When executing the code from the application, I can see that "condition 2 worked." is being called one second before "nothing worked.".
I don't understand how this can be. If debugEmail("condition 2 worked."); is executing, then so should too $hasPaymentDatabaseAttached = true; in which case this should not execute:
if (!$hasPaymentDatabaseAttached)
{
debugEmail("nothing worked.");
attachPaymentDatabase();
}
But it clearly is.
What is going on here?!?!?!?
No it shouldn't, because $hasPaymentDatabaseAttached is set to true in the first condition. In still nonsense at all, but it works as described.

returned function result is confused in conditional statement

I have a class that works with database in PHP. the Add function in this class is:
function Add($post_id)
{
if(!is_numeric($post_id))
{
return 1181;
}
$query = "...";
$result = mysql_query($query, $this->link);
return $result;
}
I also have a page that gets a form data and passes them to this class. The page code is:
$result = $obj->Add($post_id);
if($result == 1181)
{
echo 'invalid';
}
else if($result)
{
echo 'success';
}
else
{
echo 'error';
}
the returned value is 1 and the output must be 'success', but i get 'invalid' message. If i swap 'invalid' and 'success' conditional statements, everything works well, but i want to know that what's this problem for?
var_dump($result); is a good starting point. in boolean context 1181 will be converted to true, so just because it prints success don't expect that it succeeded.
You probably pass the wrong post_id. Enable displaying warnings and notices. Don't use crazy magic constants, use false or throw an exception. Always check the return value of mysql_query.
If you do that I don't have to guess and you can make progress and ask meaningful questions.
Like others have pointed out in the comments, you should be using Exceptions in these types of cases. Here's an example.
function Add($post_id)
{
if(!is_numeric($post_id))
{
throw new InvalidArgumentException( 'Argument should be numeric' );
}
$query = "...";
$result = mysql_query($query, $this->link);
return $result;
}
try
{
$result = $obj->Add($post_id);
}
catch( InvalidArgumentException $e )
{
/* handle the invalid argument exception */
}
if($result)
{
echo 'success';
}
else
{
echo 'error';
}
Furthermore, if you insist on using codes for your errors, you might use this:
function Add($post_id)
{
if(!is_numeric($post_id))
{
throw new InvalidArgumentException( 'Argument should be numeric', 1181 );
}
if($post_id <= 0)
{
throw new InvalidArgumentException( 'Argument should be larger than 0', 1182 );
}
$query = "...";
$result = mysql_query($query, $this->link);
return $result;
}
try
{
$result = $obj->Add($post_id);
}
catch( InvalidArgumentException $e )
{
switch( $e->getCode() )
{
case 1181:
/* handle the invalid argument exception with code 1181 */
break;
case 1182:
/* handle the invalid argument exception with code 1182 */
break;
default:
/* handle other invalid argument exceptions */
break;
}
}
Lastly, like others have commented also, exception handling has nothing to do with, and does not interfere with preventing SQL injection.

Categories