PHP array not setting correctly in try catch statement - php

I am using an array to log key information in a foreach statement for use later on, I set the array at the top of the page to ensure that it is available across all functions in the script.
I have tested to see that the array is set, and it seems to work outside a try catch statement see commented code below.
$completeClients = array();
if($can_synchronise === true)
{
$success = sync_to_client($package, $client);
try
{
if($success)
{
$completeClients[] = "Sync to ".$client->getName()." has completed";
}
else
{
$completeClients[] = "Sync to ".$client->getName()." has failed";
}
}
catch(Exception $ex)
{
logMsg("Unable to save client data reason: ". $ex->getMessage(), STATUS_ERROR , $client->getAddress());
}
exit( EXIT_OK );//Exit the child process
}
}
else
{
**// The array is set correctly when called here**
$completeClients[] = "Sync to ".$client->getName()." has failed";
}
I have printed the array and when it is called in the try catch statement it looks like:
Array
(
[0] => Sync to TPSDEV_PHILIPS_TWO has completed
)
Array
(
[0] => Sync to TPSDEV_TC_Client2 has completed
)
Array
(
)
It should look like
Array
(
[0] => Sync to TPSDEV_PHILIPS_TWO has completed
)
Array
(
[0] => Sync to TPSDEV_PHILIPS_TWO has completed
[1] => Sync to TPSDEV_TC_Client2 has completed
)
Array
(
[0] => Sync to TPSDEV_PHILIPS_TWO has completed
[1] => Sync to TPSDEV_TC_Client2 has completed
)
Do you guys have any idea? im stumped.

This doesn't add up:
exit( EXIT_OK );
It's outside of the try-catch block, so whatever happens (succesful or otherwise), after inserting the first value in the array, you're exiting the script. As soon as the branch if ($can_synchronise === true) gets executed once.
What's more, there's no loop to be seen anywhere, so how do you expect this to produce an array that contains more than 1 value?
There's something else, too: you're calling the sync_to_client outside of the try-catch block, which only contains an if-else and an assignment to an array. Nothing that might throw an exception AFAIK, unless $client->getName() throws, but the name implies a getter, which is unlikely to throw in the first place.
You probably want to call the sync_to_client in the try-catch, if that's the function that is likely to throw an exception.
Lastly, if this is part of a loop of some sort, and you've posted just the inner code, then you really ought to move this:
$completeClients = array();
out of the loop, because now, each time this block of code gets executed, you're reassigning $completeClients to hold a new, empty array.
Assuming an array of client objects, your code should look something like this:
$completeClients = array();
foreach($clients as $client)
{
if (!$canSynchronize)
{
$completeClients[] = 'Sync to '.$client->getName().' has failed';
continue;//messy, best wrap the try-catch in an else branch
}
try
{
if (sync_to_client($package, $client))
{
$completeClients[] = 'Sync to '.$client->getName().' has completed';
}
else
{
$completeClients[] = 'Sync to '.$client->getName().' has failed';
}
}
catch(Exception $e)
{
logMsg("Unable to save client data reason: ". $ex->getMessage(), STATUS_ERROR , $client->getAddress());
//$completeClients[] = 'Unable to Sync: '.$e->getMessage();
//exit( EXIT_OK);
throw $e;//rethrow, is what I'd do.
}
}
However, what this code effectively does is catch exceptions, and sort-of hush them up. If something fails, there's likely to be a bug in your code. Don't catch an exception unless you know how to deal with it. And don't catch everything.
PDO throws PDOException instances. SOAP clients throw SoapFault's, my objects throw either InvalidArgumentException, RuntimeException or BadMethodCallException instances. There are many types, each one of them signals a specific type of problem. Don't try to be yoda, playing pokemon

I don't know if mentioned code placed inside an array or function, however I think if you replace following with something else it can help
$completeClients = array();
with
if (!isset($completeClients)) {
$completeClients = array();
}

Related

AWS SDK EC2 - "DescribeInstances" Exception, skip instance in list

I have a list of Instances ID saved in DB.
a periodic check validates those ID's against AWS.
The problem is that if one of the instances doesnt exist then i get Exception and the whole request fails (none of the ID's return).
Is there a way to skip that missing ID and get back all data except for that specific instanceID?
My code:
$requesltArray = ['Filters' => $this->_Filters, 'InstanceIds' => $this->_InstanceIDs];
try {
$reservations = $this->_EC2Client->DescribeInstances($requesltArray)->toArray();
} catch (Ec2Exception $exc) {
echo $exc;
return [];
}
results in Exception:
aws sdk Error executing "DescribeInstances" InvalidInstanceID.NotFound
Depending of the number of instances you have, you might consider then to perform your DescribeInstances request for each individual IDs.
$reservations = [];
foreach($this->_InstanceIDs as $anInstance){
try {
$requesltArray = ['Filters' => $this->_Filters, 'InstanceIds' => $anInstance];
$aReservation = $this->_EC2Client->DescribeInstances($requesltArray)->toArray();
$reservations[] = $aReservation;
} catch (Ec2Exception $exc) {
// --> Delete the instance from your database?
continue;
}
}
dd($reservations);

Cakephp, how using try catch in action of controller

I have one model with associative data, with relation hasMany through,
Example-models:
One
OneTwo
Two
When I update my object One with containing objects OneTwo, I need to delete old objects OneTwo.
I use saveAssociated for save object One, with atomic = false.
I'm handling the transaction manually, example at fly:
$save = false;
$dataSource->begin();
try{
$One->OneTwo->deleteAll(conditions);
$saveAssociated( $one ); //if exception for anythings go catch
$save = true;
}catch( Exception $e ){
//print exception in log
}
if($save){
//commit
}else{
//rollback
}
but the block try catch is ignored for cake, in exception not go at the catch, continue normal.
as I can use a block try catch in cake??

Reverting object property changes in php

I have a bunch of Doctrine php objects and I'm calling things like
$myObj = $query->execute()->getFirst();
$myObj->setName('a new name');
$myObj->setAge('40');
$myObj->save();
etc...
etc...
And at some point, if encounter an error, I'd like to revert all those property changes since I've already called the save() function and that propagates the new properties to the database.
I'd like to come up with a way to store the old value of the object as well as which method to call to revert it. Something like:
$undoCollection = array();
$undoObject = array();
$undoObject['revertFunction'] = $myObj->setName;
$undoObject['revertValue'] = 18;
array_push($undoCollection,$undoObject)
So that later on, if something goes wrong, I can loop through the $undoCollection:
foreach($undoCollection as $undoObj)
{
$undoObj['revertFunction']($undoObj['revertValue']);
}
Is this something that's possible in PHP? Or is there something else that can provide that functionality?
You should use transactions. E.g.:
$myObj = $query->fetchOne();
if ($myObj)
{
$conn = $myObj->getTable()->getConnection();
try
{
$conn->beginTransaction();
$myObj->setName('Asd')->save();
// do other stuff...
// if an exception is thrown before calling commit
// nothing in this try block will be saved
$conn->commit();
}
catch(Exception $e)
{
$conn->rollback();
}
}

Catching Exceptions in OO PHP

I have a class Person.
I want to add error handling into my script, so that say, the user enters an incorrect email address the script will tell them. Usually not a problem at all, but now I am using OO classes I am in unfamiliar territory.
So. I guess I want to know how to handle multiple exceptions. Or do I need to try each line of code one at a time and catch each line? This seems slightly excessive. Ideally I'd like to do the following:
try {
$people[$new]->set_fullname($_POST['name']);
$people[$new]->set_active(true);
$people[$new]->set_add1(rEsc($_POST['add1']));
$people[$new]->set_add2(rEsc($_POST['add2']));
$people[$new]->set_add3(rEsc($_POST['add3']));
$people[$new]->set_add4(rEsc($_POST['add4']));
$people[$new]->set_postcode(rEsc($_POST['postcode']));
$people[$new]->set_phone(rEsc($_POST['phone']));
$people[$new]->set_email(rEsc($_POST['email']));
} catch {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
But in my error handling, How can I catch multiple errors? I'd like to push all the error messages into an array and display them each nicely in the webpage. As far as I can see on php.net it seems that I can only catch one error message at a time.
Do I really have to try {} catch {} each line of code?
Imho this shouldn't throw exceptions in the first place. Simply loop through the fields and add the possible errors to some $errors array.
Users screwing up fields is not an exceptional case. I don't even think the user object should be able to validate an emailaddress. That seems to be like a responsibility of the Form.
Also am I wondering what that rEsc function is you are using. Not only are you using a global function which makes it virtually impossible to swap it out for some other function in the future (tight coupling), but also the name is chosen badly. Also do I fail to see why you would want to escape stuff in that place (I guess that is what the thing does). Only escape / sanitize data when you are using it. And I'm wondering for what you are escaping your data, because if it is for database input there are far better ways.
try {
$people[$new]->set_fullname($_POST['name']);
$people[$new]->set_active(true);
$people[$new]->set_add1(rEsc($_POST['add1']));
$people[$new]->set_add2(rEsc($_POST['add2']));
$people[$new]->set_add3(rEsc($_POST['add3']));
$people[$new]->set_add4(rEsc($_POST['add4']));
$people[$new]->set_postcode(rEsc($_POST['postcode']));
$people[$new]->set_phone(rEsc($_POST['phone']));
$people[$new]->set_email(rEsc($_POST['email']));
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
} catch (EmailFormatException $em) {
echo 'Caught exception: '. $e->getMessage();
}
Just continue it like that
Here's how I would design this:
Create a validate() method on the Person class that verifies every property and returns an array of strings that explain the errors to the user. If there are no errors, have the method return null.
Do not use exceptions at all. They are slow; they complicate code maintenance (and you're seeing the symptoms in the approach you've taken so far)
Remove the custom methods for setting properties of the Person object. PHP is not Java. Set the properties directly.
Putting this all together:
class Person {
public $name;
public $address1;
public $address2;
public function validate() { }
}
And then your code:
$obj = new Person();
$obj->name = "Bob";
$obj->address1 = "1 Elm St.";
$validationResult = $obj->validate();
if ( $validationResult != null) { // there were errors
print_r($validationResult);
}
You can make a foreach statement that sets the data that needs validation with try/catch inside the loop in order to populate an array with the errors, like that:
$errors = [];
foreach (['field1', 'field2', ...] as $field) {
try {
$method = "set_{$field}";
$people[$new]->$method(rEsc($_POST[$field]));
} catch (Exception $e) {
$errors[] = $e->getMessage();
}
}

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
}
}

Categories