1

Please advise what's going on here?

We have the following classes working together:

  • An abstract base class 'form element'
  • An abstract 'container' class that extends the form element class and groups form elements
  • A 'field' class that extends the container

In the 'field' class we call a method from the 'form element' class named 'setErrors($vars)' that sets a property named 'hasErrors'. $vars carries a boolean.

There is another method named 'hasErrors()' in the 'form element' class that we try to call in the 'field' class to test the result of the boolean previously set however it returns false.

The hasErrors property that is initially declared as false is not being overwritten?

Form Element Class(Base)

private $hasErrors = false;

public function setErrors($flag)
{
...
$this->hasErrors = $flag;
...
}

public function hasErrors()
{
return $this->hasErrors;
}

Field Class

public function validate($value)
{
...
$this->setErrors($foundErrors);//$foundErrors only local to this method
...
}

public function getField()
{
...
   if($this->hasErrors())
   {
   //do something...
   }
...
}

Why is the property 'hasErrors' not being overwritten? Would this have something to with the scope of inheritance between the different classes?

Not sure how this works but thanks in advance.

3
  • I think this has maybe confused people by being the same name. The $hasErrors variable in the 'field' class is only local to the 'validate' method. Its just to pass as an argument in the 'setErrors' method. Maybe I should edit the code to show this as $isErrors? Commented Apr 27, 2011 at 13:13
  • This should work. In validate you are setting the value using the public setter method setErrors. That's perfectly legal. But where is the if($this->hasErrors()) located? If I put it inside the validate method (you have it outside somewhere), it works properly, as it should. Whoops, nevermind. I overlooked that you have a container class, too (class field extends container extends formelement). Commented Apr 27, 2011 at 13:18
  • Sorry I have edited the code to show how the 'hasErrors()' method is being called and changed local variable name in 'validate()' method because this was confusing. The $foundErrors(renamed) boolean variable is passed to the 'setErrors()' method. This is not the same as the $hasErrors property in the base class. Commented Apr 27, 2011 at 13:36

2 Answers 2

2

you must declare $hasErrors as protected property not private.

private methods are not inherited.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for your quick response but surely this doesnt matter in this case because we are setting the property inside the base class and trying to call a public method to get the results in the subclass. I changed it anyhow and it doesnt help.
yes but when you call setError method it's trying to set child class property not the base.
This is not true, it will set them just fine.
What's not to true? that private methods are not inherited? :D
? You will not be able to access $this->hasErrors directly, however setting them via the public methods on the same base class will work perfectly fine, see my answer. hasErrors is both a public method and a private field, he's utilising the public method in the extension class.
0

I'm sorry to not answer your question directly, but the other answers are misleading and feel I have to step in a bit. Especially since similar test code works fine.

Have you tried stripping your code down to the basics? Just as a test, I created the following which works fine:

<?php
class test {
        private $var = 'unset';
        public function setVar($val) {
                $this->var = $val;
        }
        public function getVar() {
                return $this->var;
        }
}
class another extends test {
        public function __construct() {
                echo $this->getVar() . "\n";
                $this->setVar('set');
                echo $this->getVar() . "\n";
        }
}
class third extends another {
        public function __construct() {
                parent::__construct(); // This will output 'unset\nset\n'
                $this->setVar('set second');
                echo $this->getVar() . "\n";
        }
}
$a = new third();

Output:

> php tmp.php 
unset
set
set second

Updated as per comment, same output:

class another extends test {
        public function methodAnother() {
                echo $this->getVar() . "\n";
                $this->setVar('set');
                echo $this->getVar() . "\n";
        }
}
class third extends another {
        public function methodThird() {
                $this->setVar('set second');
                echo $this->getVar() . "\n";
        }
}
$a = new third();
$a->methodAnother();
$a->methodThird();

5 Comments

I think this could answer everything but Im not as quick as some of you so will let you know, cheers.
Thank you very much Rudi, your approach to analysing the issue is very good indeed. It works if you call the 'setErrors()' method in the constructor of the 'field' class like your example(third) but not from anywhere else in the class like in our code. If the answer to this is fairly simple please could you explain why? Would be much appreciated.
Hi Steve, sorry but that should still work fine, I amended another and third to have another method each that does the constructor code. Please see extension to my answer (sorry it's getting a bit long).
Thanks Rudi, you have been a great help. Your examples work fine but I think the issue with what we are doing is how the object is instantiated which is another question, cheers.
Alright, not a problem. Sorry about the wrong answers posted here before, OOP concepts are lost on most PHPers :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.