Home > other >  Why does my PHP class seem to be looping if I declare a property as an array outside of the method?
Why does my PHP class seem to be looping if I declare a property as an array outside of the method?

Time:02-10

I have a class that essentially runs through a matching pair of arrays to do some error correction:

class PumpErrors {
    public $error = array();
    private $pumpdat;
    private $welldat;
    
    public function __construct($pumpdat, $welldat){
        $this->pumpdat = $pumpdat;
        $this->welldat = $welldat;                            
    }
   
    public function firstOfAll() {
        $i = 0;
        foreach($this->pumpdat as $val){
          if(!is_numeric($val)){
                
                $err = $this->welldat[$i].' must be a number and cannot be blank.  Use 0 for no amount pumped.';
                $this->error[] = $err;
            } 
            $i  ;
        }
        return $this->error;
    }  
}      

$errors = new PumpErrors($_POST['pumpamt'], $_POST['wellid']);

I'm feeding the class the array from the form (POST) (its a matched pair of an amount and ID of a pump. The number of pumps varies depending on who is using the form.) I then call the errors on the main page to show the errors:

<?php 
if(isset($errors)){
?>
    <div class='form-row justify-content-center'><p class='text-danger'>
<?php   
    foreach($errors->firstOfAll() as $userErrors) { 
        echo $userErrors . '<br />';
    
?>
        </p>
    </div>
<?php 
    } 
?>

This results in the errors being displayed TWICE.

Pump 12 must be a number and cannot be blank. Use 0 for no amount pumped.
Pump 12 must be a number and cannot be blank. Use 0 for no amount pumped.

HOWEVER

If I run the class like this:

class PumpErrors {
    public $error;
    private $pumpdat;
    private $welldat;
    
    public function __construct($pumpdat, $welldat){
        $this->pumpdat = $pumpdat;
        $this->welldat = $welldat;                            
    }
   
    public function firstOfAll() {
        $this->error = array();
        $i = 0;
        foreach($this->pumpdat as $val){
           
            if(!is_numeric($val)){
                
                $err = $this->welldat[$i].' must be a number and cannot be blank.  Use 0 for no amount pumped.';
                $this->error[] = $err;
            } 
            $i  ;
        }
        return $this->error;
    }  
}     
        
$errors = new PumpErrors($_POST['pumpamt'], $_POST['wellid']);

and display the errors, it only shows up once, as intended.

I'm just looking for an explanation as to WHY this would be happening.

If I declare the property as an array at the beginning, I get doubles on the output.

If I set the property initially as nothing and then set property as an array inside the method, all is good.

I initially thought that perhaps declaring it as an array at the beginning was causing it to be a multidimensional array and somehow the loop through to display it was just going through it twice. But the kint dump didn't look as if that was happening. If there is more than one error say pump 1 and pump 2, then i get doubles like this:

Pump 1 (error message)
Pump 2 (error message) 

Pump 1 (error message) 
Pump 2 (error message)

(note:, im doing this as a class out of laziness so i can use the same error display code as rakit validator for the rest of the form, I know there are easier way to run thru the array to check it. This was more of an exercise to see IF it could be done this way and I stumbled on this weird behavior.)

EDIT: perhaps a version issue? im running it on 7.4.24 locally.

CodePudding user response:

In the first version of the class you only clear the errors array when the class is instantiated

public $error = array();

But in the second version you clear the errors array as part of the the call of the method

public function firstOfAll() {
    $this->error = array();

So of course the errors in the first version will just keep building up over multiple calls to firstOfAll() but in the second each call initialises the errors array.

CodePudding user response:

If you define the variable as a "Static public $error", this should eliminate this variable from be instantiated each time a new object of the class is created.

  •  Tags:  
  • Related