How to jump from one Function to another in PHP Class - php

I have a php script to pipe through a mail,
class mailTest
{
// (some code here)
private function saveToDb()
{
// (some code here)
$select = $this->pdo->query("SELECT * FROM tbl_reques WHERE terminal_id = $term AND request_status ='' ");
$select = $select->fetchAll();
if (count($select) > 0) {
echo "Call already Exist (DISCARD)";
} else {
$select_tech = $this->pdo->query("SELECT * FROM tbl_email WHERE terminal_id = $term");
$select_tech = $select_tech->fetchAll();
// (some code here)
}
}
private function sendEmail()
{
$this->today = time();
$this->maildate = date("Y-m-d H:i:s", strtotime('-5 minutes', $this->today));
$select = $this->pdo->query("Select * from tbl_reques WHERE maildate >= '$this->maildate' ");
// some code here
mail($this->from_email, $this->subject, $newmsg, $headers);
}
}
The problem is any time the condition is False i.e echo "Call already Exist (DISCARD)"; The code will not go to the Next Function. i.e the program get halt.
PLS is there a way that if that condition is not met, the program will JUMP to next function for continuation of execution. Or is it possible to use GOTO statement.
Pls what is the best way to handle this in PHP.
Thanks

You have a couple option for this. You can return at the point of failure. Which would exit the function at this point and then do whatever is next in the script being ran. Be sure to do the clean up before your return.
if(count($select) > 0) {
echo "Call already Exist (DISCARD)";
//Clean up if needed
return; //You could also return the message
//or an error code and have another
//evaluation based on that.
} else {
// Or passes
}
You could call the next function but this would be a very bad flow in my opinion
if(count($select) > 0) {
echo "Call already Exist (DISCARD)";
//Clean up if needed
$this->sendEmail();
} else {
// Or passes
}
The reason this would be bad is if say in the script you have
$mailTest = new mailTest();
$mailTest->saveToDb();
$mailTest->sendEmail(); //When the above fails this is called twice.
You could likewise throw an exception
if(count($select) > 0) {
echo "Call already Exist (DISCARD)";
throw new Exception("Call already Exist (DISCARD)");
} else {
// Or passes
}
Now you need to use try and catch
$mailTest = new mailTest();
try {
$mailTest->saveToDb();
catch (Exception $e){
//Do something with $e
//Clean up the failure if needed
}
$mailTest->sendEmail();
There is a finally block as well which would run in cases where your catch stops the script.

PHP in fact has a GOTO statement, see http://php.net/manual/de/control-structures.goto.php
However, it is considered bad style to use it, or in the words of #Konamiman
Unless you are programming in assembler, GOTO should always be treated the same way as the life vest of the airplanes: it is good to have them available, but if you need to use them it means that you are in big trouble.
You can call a function simply by writing its name followed by brackets. In the case of class functions you apply it to $this:
$this->sendEmail();

Related

doctrine2 flush() silently crashes for no apparent reason

I'm writing a converter that takes a document from database (mongo db), does some magic with its fields and writes it back. Repeat for all relevant docs.
The problem is, after successful processing EntityManager#flush() just silently crashes not committing any changes to db or returning an error code.
I encountered this crash before but I've been able to evade it by reducing quantity of entities to flush(). Now it won't work even with one.
The code goes like this:
public function convertTagsAction() {
$result = [];
$result['docs processed'] = 0;
$result['tags added'] = 0;
$repo = $this->getRepo('Portal');
$cnt = 0;
$dm = $this->getDM();
$docs = $repo->findBy([...]);
$result['docs to process'] = count($docs);
foreach($docs as $doc) {
....//executing just for ONE doc at the moment
$result['docs processed']++;
//file_put_contents('1.txt', print_r($doc, true));
//Everything is ok in the file
$dm->persist($doc);
echo $dm->getUnitOfWork()->size();
// returns 6087 which I deem strange
//this helped me before to manage this problem
$cnt++;
if ($cnt >= 20) {
$dm->flush();
$cnt = 0;
}
}
try {
$dm->flush();
} catch (Exception $e) {
echo $e->getMessage(); //Nah, won't tell me anything
}
return $this->success($result);
}
So now, whenever flush() is called, the script just quits and not even returns any output (should do so in the last line). Any ideas how to solve it?

Returning true/false in functions with a message to further explain the reason why it returned false

I'm creating functions where I want to be able to output true or false pertaining to if statements within the function are met. An example of this is like this:
function pokeme($number){
if($number > 10)
{
return true;
}
else
{
return false;
}
}
However, one problem with this approach is that if the function returns false, you wont be able to decipher which false means what, especially if there is more than one if/else statements.
My question is, how do I output a false plus a way to later identify what that false was?
Do I do an array?
return array("false", "message pertaining to whatever");
However, if that is done, you can't really do this, plus...:
if(pokeme()){ /*success*/ } else { /*there may be multiple falses for different situations... how do I distinguish what it is? */}
Note that the way the idea is demonstrated here might not be the best, but once you get te hang of it, it gets easier. Also, read end note, please.
If you want to use like this (true is expected and false is problem):
if(pokeme()){ /*success*/ } else { /* not needed */}
You can do something like this:
function pokeme($number){
//let's say you want to return true if it's >10 and -9 to -1
if($number > 10){
// do something
return true;
}
if($number < 0 && $number > -10){
return true;
}
// handling multiple problems (just 2 ^^)
if($number < -9){
throw new Exception("Invalid input. Can't use negative smaller than -9.");
}
throw new Exception('Invalid input. Expected bigger than 10.');
}
Two tests:
try{
echo "RESULT1 :".pokeme(-42).":"; // not shown (error in this line)
echo "RESULT2 :".pokeme(11).":"; // not shown
}catch(Exception $e){
echo "Error: '".$e->getMessage()."'"; // Just the message
}
echo "<br><br>";
try{
echo "RESULT3 :".pokeme(11).":<br>"; // shown
echo "RESULT4 :".pokeme(10).":"; // not shown (error in this line)
}catch(Exception $e){
echo $e; // Full error
}
You can use it like this:
try{
if(pokeme(11)){
echo "VALID INPUT<br>";
}
if(pokeme(5)){
echo "I'm not seen :\\";
}
}catch(Exception $e){
echo "Error: '".$e->getMessage()."'";
}
End note: Think of this like you are using a built-in php function that might cause an error. This way you have to handle it with a try..catch.
More about Exceptions.
For fully automated input validations you can make use of the Symfony form component, and its Validation.
You can also add very simple constraints like LessThan(10) exactly like in your example, and the component automatically writes the appropriate error message back to your page (and the invalid form e.g. dont performs DB inserting).
It exists a lot of prepared constraints to use, you can also create own ones.
Or if you want to write all by your self, i suggest you to read OOP and Exception handling before.
EDIT
If you want to "collect" errors with its messages, solving this procedural for your code example (not recommended) you can store this messages in a temporary array in the superglobal variable $_SESSION. I explicitly say superglobal variable. Dont use a global variable and inject it with the global key, this will become very complex code in long therm.
Anyway my idea using $_SESSION. This code works for me:
<?php
session_start();
// Resetting the tmp session array on every page reload. That previous error messages are resetted.
$_SESSION['errors'] = array();
function printSessionErrors()
{
// Print errors stored in the session if some exists
if (array_key_exists('errors', $_SESSION)) {
foreach ($_SESSION['errors'] as $i => $error) {
$success = true === $error['success'] ? 'true' : 'false'; // Only for print
$message = $error['message'];
echo "Success: $success. Message: $message <br>";
}
}
}
function pokeme($number)
{
$expected = 10;
$success = null;
if ($number > $expected) {
$success = true;
} else {
$_SESSION['errors'][] = array(
'success' => $success,
'message' => "Number $number is less than $expected"
);
$success = false;
}
return $success;
}
pokeme(1);
pokeme(7);
pokeme(99);
printSessionErrors();
Now depending on if it was a form POST or procedural validation you add printCleanSessionErrors() on top (after session_start()) or on bottom on the code.
I get this output:
Success: false. Message: Number 1 is less than 10
Success: false. Message: Number 7 is less than 10
You only have to add the $_SESSION['errors'][] = array .... into your other error situations.
That's one of those questions, which, being very poorly phrased, lead to completely wrong answers.
Before asking such a question, one has to realize that there are two kinds of functions:
functions that perform some action
functions that do nothing but just verify the parameter, telling whether it's right or wrong
And the approach for these two kinds must be completely different.
In case pokeme() function has to use the $number parameter somehow, but for some reason cannot do that, then an exception must be thrown. Because it's the very purpose for exceptions: to handle the exceptional behavior. In this case, the function will never returns false, so it makes no sense to return true either. So it will be either the correct result or exception will be thrown. But it is important to understand that as a rule, exceptions shouldn't be caught on the spot. Least an exception has to be used to convey some message from a function.
An exception should be used only if a function is unable to do its job:
function divide_by($number, $divisor)
{
if (!is_numeric($number) || !is_numeric($divisor)) {
throw new InvalidArgumentException("The arguments must be nubmers");
}
if ($divisor === 0) {
throw new InvalidArgumentException("Cannot divide by zero");
}
return $number / $divisor;
}
In case pokeme() function, as it shown in the example provided, has to test the $number somehow, and tell if it's all right or not, no exceptions have to be used. Because wrong value is not an exceptional case.
Here, the simplest approach to convey the message would be to reverse the function's "polarity" and make it return false in case the parameter is all right, and a true-ish value in case it's wrong. Which will allow us to return the very message we need.
function check_number($number)
{
if(!is_int($number))
{
return "The value provided is not numeric";
}
if($number < 10)
{
return "The number is less than 10";
}
return false;
}
and then it can be used like this
$error = check_number($number);
if(!$error) {
/*success*/
} else {
$errors[] = $error;
}
But this approach is rather silly. A more robust solution would be to write a class, utilizing such a handy feature as class variables
class NumberValidator
{
protected $error;
public function validate()
{
if(!is_numeric($number))
{
$this->error = "The value provided is not numeric";
return false;
}
if($number < 10)
{
$this->error = "The number is less than 10";
return false;
}
return true;
}
public function getError()
{
return $this->error;
}
}
and then it can be used like this
$validator = new NumberValidator();
if($validator->validate($number)) {
/*success*/
} else {
$errors[] = $validator->getError();
}

PHP PDO. Should I throw an exception if update query rowcount is zero?

I am working on my first OO PHP website.
When I am calling an update function, for example to unblock an user, I will check if this was successful. If not I will throw an exception like this:
Business layer code:
if($DB->unblockUserByUsername($username) === FALSE){
throw new DBExpectedRowUpdate("Expected row update.");
}
Called function in DB Class:
public function unblockUserByUsername($input){
$sql = "UPDATE user SET ......"; //<- imagine valid update query
return $this->updateQuery($sql) === 1; // Return bool
}
I thought, I don't have update functions where I don't expect a row to be updated. So I will end up doing this check every time I call an update function in my upper layer.
So I thought isn't it better to throw this exception in the DB class update function itself? Like:
private function updateQuery($sql, $dontThrowError = FALSE){
$this->CheckConn(); try {
$affectedRows = $this->DBH->exec($sql.";");
$this->DBH->commit();
//Check affected rows count
if($affectedRows === 0 && $dontThrowError !== TRUE){
throw new DBExpectedRowUpdate("Expected row update.");
}
return $affectedRows;
} catch(PDOException $e) {
$this->DBH->rollback();
return -1; // Also throw error here
}
}
I am asking this because I can't seem to find a lot about this subject or best practice examples for a similar case.

Php for loop with try catch

This question is in continuation from this as suggested by one of the user.
I am using the getIDs function as below to process the id's. CheckValid() will check if the id's is a valid one to be processed, if yes then it will go to the next one updateUsers(). Check valid just checks for a condition and if not it throws an exception. updateUsers() just updates a column if it passes checkValid().
Problem – If I get 4 id's as output from getIDs(), and with the execute(), it process 2 for example and if it fails for 2nd id, it doesn't continue for the rest 2 id's ..I want it to continue so I commented out the "throw $e in the catch block".
Function execute() {
for($i=0 ; $i<count($this->getIDs()); $i++) {
try {
$this->checkValid();
$this->updateUsers();
} catch(Exception $e) {
//throw $e;
}
have you try a simple continue in the catch block ? didn't test but maybe something like that:
Function execute() {
for($i=0 ; $i<count($this->getIDs()); $i++) {
try {
$this->checkValid();
$this->updateUsers();
} catch(Exception $e) {
//throw $e;
continue; // if not working try a continue 2;
}
}
}
It sounds like you're using exceptions as booleans, I'd suggest avoiding that, as it gets confusing quickly, unless you really need the contents of the exception. See if this makes any sense for your use case (I'll grant, it may not).
// returns true if valid, false otherwise
function checkValid(){
try {
// do your validation
return true;
} catch (Exception $e) {
// optional: save the exception in case we want to know about it
$this->last_error = $e;
return false;
}
}
function execute() {
for($i=0 ; $i<count($this->getIDs()); $i++) {
if($this->checkValid()){
$this->updateUsers();
}
// if you want to do something with an error, simply add an else clause
// and handle $this->last_error
}
}
Also, I obviously don't know your code or what exactly you're doing, but looping n times and calling checkValid() and updateUsers() without parameters seems like very poor practice. Much better to, for instance, loop over the list of IDs and check each ID and user in turn, something like this:
foreach($this->getIDs() as $id){
if($this->checkValid($id)){
$this->updateUser($id);
} else {
// an advantage of this is now we can know exactly which ID failed,
// because we have the $id variable
}
}

PHP Exceptions in Classes

I'm writing a web application (PHP) for my friend and have decided to use my limited OOP training from Java.
My question is what is the best way to note in my class/application that specific critical things failed without actually breaking my page.
My problem is I have an Object "SummerCamper" which takes a camper_id as it's argument to load all of the necessary data into the object from the database. Say someone specifies a camper_id in the query string that does not exist, I pass it to my objects constructor and the load fails. I don't currently see a way for me to just return false from the constructor.
I have read I could possibly do this with Exceptions, throwing an exception if no records are found in the database or if some sort of validation fails on input of the camper_id from the application etc.
However, I have not really found a great way to alert my program that the Object Load has failed. I tried returning false from within the CATCH but the Object still persists in my php page. I do understand I could put a variable $is_valid = false if the load fails and then check the Object using a get method but I think there may be better ways.
What is the best way of achieving the essential termination of an object if a load fails? Should I load data into the object from outside the constructor? Is there some sort of design pattern that I should look into?
Any help would be appreciated.
function __construct($camper_id){
try{
$query = "SELECT * FROM campers WHERE camper_id = $camper_id";
$getResults = mysql_query($query);
$records = mysql_num_rows($getResults);
if ($records != 1) {
throw new Exception('Camper ID not Found.');
}
while($row = mysql_fetch_array($getResults))
{
$this->camper_id = $row['camper_id'];
$this->first_name = $row['first_name'];
$this->last_name = $row['last_name'];
$this->grade = $row['grade'];
$this->camper_age = $row['camper_age'];
$this->camper_gender = $row['gender'];
$this->return_camper = $row['return_camper'];
}
}
catch(Exception $e){
return false;
}
}
A constructor in PHP will always return void. This
public function __construct()
{
return FALSE;
}
will not work. Throwing an Exception in the constructor
public function __construct($camperId)
{
if($camperId === 1) {
throw new Exception('ID 1 is not in database');
}
}
would terminate script execution unless you catch it somewhere
try {
$camper = new SummerCamper(1);
} catch(Exception $e) {
$camper = FALSE;
}
You could move the above code into a static method of SummerCamper to create instances of it instead of using the new keyword (which is common in Java I heard)
class SummerCamper
{
protected function __construct($camperId)
{
if($camperId === 1) {
throw new Exception('ID 1 is not in database');
}
}
public static function create($camperId)
{
$camper = FALSE;
try {
$camper = new self($camperId);
} catch(Exception $e) {
// uncomment if you want PHP to raise a Notice about it
// trigger_error($e->getMessage(), E_USER_NOTICE);
}
return $camper;
}
}
This way you could do
$camper = SummerCamper::create(1);
and get FALSE in $camper when the $camper_id does not exist. Since statics are considered harmful, you might want to use a Factory instead.
Another option would be to decouple the database access from the SummerCamper altogether. Basically, SummerCamper is an Entity that should only be concerned about SummerCamper things. If you give it knowledge how to persist itself, you are effectively creating an ActiveRecord or RowDataGateway. You could go with a DataMapper approach:
class SummerCamperMapper
{
public function findById($id)
{
$camper = FALSE;
$data = $this->dbAdapter->query('SELECT id, name FROM campers where ?', $id);
if($data) {
$camper = new SummerCamper($data);
}
return $camper;
}
}
and your Entity
class SummerCamper
{
protected $id;
public function __construct(array $data)
{
$this->id = data['id'];
// other assignments
}
}
DataMapper is somewhat more complicated but it gives you decoupled code which is more maintainable and flexible in the end. Have a look around SO, there is a number of questions on these topics.
To add to the others' answers, keep in mind that you can throw different types of exceptions from a single method and handle them each differently:
try {
$camper = new SummerCamper($camper_id);
} catch (NoRecordsException $e) {
// handle no records
} catch (InvalidDataException $e) {
// handle invalid data
}
Throwing an exception from the constructor is probably the right approach. You can catch this in an appropriate place, and take the necessary action (e.g. display an error page). Since you didn't show any code, it's not clear where you were catching your exception or why that didn't seem to work.
try {
$camper = new SummerCamper($id);
$camper->display();
} catch (NonexistentCamper $ex) {
handleFailure($ex);
}

Categories