I'm creating a website but, in order to further my coding skills, I'm trying to do it utilising the power of OOP.
I'm using classes to validate form input so thought I'd have a 'parent' validation class and then child classes for each form that gets submitted (i.e. login class, registration class etc) that would take care of putting the right values into the database etc.
The code I've seen has the parent being constructed from the child's constructor. However, I've not done that but my class seems to work anyway?
Could someone explain to me why we call the parent constructor from the child?
Also, is my code only working because I have 'public' functions (methods) in my parent? (is this potentially an issue)?
My code (abridged version for clarity) is below:
class Validation_Class
{
public function __construct()
{
// constructor not needed
}
public function is_genuine_email_address($email) {
// code to validate email are genuine here...
}
}
My child class looks like...
class Login_Class extends Validation_Class
{
public function __construct()
{
// I don't call parent::__construct() from here
// should I be doing?
// I can still access parent methods with $this->is_genuine_email_address
}
}
All my functions (methods) in my Validation_Class are 'public' and when I instantiate my child class I can call any of the Validation Class methods with:
$className = "Login_Class";
$thisClass = new $className();
It is not nessecary to call the parent constructor
class Parent {
//maybe just holding some constants
public $database = 'mydatabase';
}
class Child extends Parent {
public function myFunction() {
if ($this->database == 'myDatabase') {
// you can access the parents data without calling a constructor
}
}
}
Is good. But if you want to benefit from something the parent has to do itself in order to work properly, a call to the parent __construct could be needed - like
class Parent {
public $database = null;
public function __construct() {
// example -> login to database
}
}
class Child extends Parent {
public function __construct() {
parent::__construct();
// .. further code
}
public function myFunction() {
// do something, like executing a query
$this->database->executeQuery($SQL);
}
}
In PHP "OOP", which is not real OOP like you see in other languages, constructors are just shorthands for instantiating the resulting object. It would be a hell if we over and over should call
$object = new MyClass();
$object->instantiate()
so calling __construct or new ClassName() is easier. But it is not absolutely needed for the class-successors to work properly, that they call constructors up in the class-hierarchy. Unless, of course, some certain initialization is needed in one of the class parents to let the successors work properly.
From an architecture perspective this would not make much sense. Because using OO inheritance is not just about extending a class in the code but also also designing and structuring your class hierarchy in such a way that it makes sense.
From a logic structuring stamp point I would not imagine a Login class to inherit from a validation class. Rather I might have a validation class object as a member of the Login class and use its functions to perform validations.
From inheritance perspective always remember that we should strive to have classes that represent 'Objects' and not 'Actions'. Of course we can have classes for Login and Validation actions, but actions rarely inherit in a parent-child fashion. They complement each other better an class members.
Calling a parent class, be it constructor or a standard method is not mandatory. It is required if you are having part of an action specified in the parent and more fine-grained action will be defined in the child.
The rule of the thumb is that as you traverse up an inherited class chain it becomes more and more generic and as you traverse down, it becomes more and more specialized.
Rather than using inheritance, using Strategy pattern for validation is one of the popular patterns available. This makes the code more modular and extendible,
Validating Incoming Data with the Strategy Design Pattern
Related
So let's say I have classes called parent and child, which will be then used from PHP file called caller.php
class Child extends Parent {
}
class Parent {
public function parentMethod(){
}
}
caller.php
PREVENTED:
$child = new Child();
$child->parentMethod();
ALLOWED:
$parent = new Parent();
$parent->parentMethod();
I want to prevent calling parentMethod like this. But if I created Parent object I want to be able to call the parentMethod. Is there some way that I can use to hide this method from being public in Child class, but still allowing parent object to call this method publicly?
Only solution I have come up with so far is making those methods protected and then creating an other class that would extend parent and then have public method for each function that it needs, but that doesn't sound very smart.
Actually, you should ask yourself: why do you need such restriction? You've defined your method as public - thus, you told PHP that it should be visible everywhere. So to prevent child calls you should use private visibility definition.
There is a way to check if call is made from parent class, like:
class ChildClass extends ParentClass {}
class ParentClass
{
public function parentMethod()
{
if(get_class($this) != __CLASS__)
{
throw new LogicException("Somehow due to business logic you're not allowed to call this from childs");
}
}
}
But I would not recommend to do that. Reasons are:
Readability. Your method is just ordinary public method. Looking to it it's impossible to say either you should use it with child calls or not. Thus, to maintain such code you'll need to check that restriction in code. Now imagine that you have ~50 methods like that. And dozen of classes like that.
Possibly, breaking Law of Demeter. Why should parent class be aware of it's childs when using such limitation?
Finally, it's just unexpected behavior. Looking to definition, anybody will see that you're extending one class by another. Thus, by definition all inherit methods with proper visibility must be inherited. And your logic changes that.
You may think about composition, not inheritance. That may be right way to implement your logic (however, I can't tell that for sure since I don't know whole background)
You can rearrange your code by adding a base parent class for both of your mentioned classes. Like so:
class Base {
public function inheritableMethod1() {}
public function inheritableMethod2() {}
}
class Child extends Base {
}
class Parent extends Base {
public function additionalMethod() {}
}
Move all inheritable methods from the Parent class to the Base, and leave there only those which must not be called on Child (the parentMethod in your example).
The base class optionally might be abstract to prevent instantiating it directly.
Check if Abstract Class suits your needs:
PHP: Class Abstraction
class Child extends Parent {
public function parentMethod(
# Code
}
}
Abstract class Parent {
abstract public function parentMethod();
}
I'm changing my class structure around to store common database methods in one class. Then extending it from a child class. This should cut down on code but also allows me to overwrite the parent methods when I need to.
I've done the following, for this example I've simplified to the basics compared to the original code which contains more classes.
class parent_object{
private $table_name;
public function all_records(){
$sql = "SELECT * FROM ".$this->table_name;
return $this->execute_sql($sql);
}
}
class child_object extends parent_object{
protected static $table_name="tbl_name";
public function __construct(){
parent::__construct(self::$table_name);
}
}
I want to call the all_records() statically to save myself creating a new object every time.
I'm stuck having to instantiate the child and then call the parent method
$child = new child_object();
$all = $child->all_records();
What I really want to be able to call the parent method statically:
$all = child_object::all_records();
I understand why I can't do it with my code, but would like some way that the child instantiates first then accesses the parent method.
I could write all_records() method in the child_object to instantiate itself and call the parent all_records() but that sort defeats the purpose of extending to cut down on code and the same methods in my child class.
I'm sure its quite simple or some new high level oop function can do it.
Thanks for your help.
The answer is relatively simple, you can turn all your properties into static properties, and then use static:: instead of self::.
http://php.net/manual/en/language.oop5.late-static-bindings.php
Solving your problem this way is considered a bad practice though. Good luck.
You could do something like this:
class child_object extends parent_object
{
protected static $table_name="tbl_name";
public static function factory()
{
return new child_object();
}
public function __construct()
{
parent::__construct(self::$table_name);
}
}
Then when you use it you just do:
$all = child_object::factory()->all_records();
So let's say I have classes called parent and child, which will be then used from PHP file called caller.php
class Child extends Parent {
}
class Parent {
public function parentMethod(){
}
}
caller.php
PREVENTED:
$child = new Child();
$child->parentMethod();
ALLOWED:
$parent = new Parent();
$parent->parentMethod();
I want to prevent calling parentMethod like this. But if I created Parent object I want to be able to call the parentMethod. Is there some way that I can use to hide this method from being public in Child class, but still allowing parent object to call this method publicly?
Only solution I have come up with so far is making those methods protected and then creating an other class that would extend parent and then have public method for each function that it needs, but that doesn't sound very smart.
Actually, you should ask yourself: why do you need such restriction? You've defined your method as public - thus, you told PHP that it should be visible everywhere. So to prevent child calls you should use private visibility definition.
There is a way to check if call is made from parent class, like:
class ChildClass extends ParentClass {}
class ParentClass
{
public function parentMethod()
{
if(get_class($this) != __CLASS__)
{
throw new LogicException("Somehow due to business logic you're not allowed to call this from childs");
}
}
}
But I would not recommend to do that. Reasons are:
Readability. Your method is just ordinary public method. Looking to it it's impossible to say either you should use it with child calls or not. Thus, to maintain such code you'll need to check that restriction in code. Now imagine that you have ~50 methods like that. And dozen of classes like that.
Possibly, breaking Law of Demeter. Why should parent class be aware of it's childs when using such limitation?
Finally, it's just unexpected behavior. Looking to definition, anybody will see that you're extending one class by another. Thus, by definition all inherit methods with proper visibility must be inherited. And your logic changes that.
You may think about composition, not inheritance. That may be right way to implement your logic (however, I can't tell that for sure since I don't know whole background)
You can rearrange your code by adding a base parent class for both of your mentioned classes. Like so:
class Base {
public function inheritableMethod1() {}
public function inheritableMethod2() {}
}
class Child extends Base {
}
class Parent extends Base {
public function additionalMethod() {}
}
Move all inheritable methods from the Parent class to the Base, and leave there only those which must not be called on Child (the parentMethod in your example).
The base class optionally might be abstract to prevent instantiating it directly.
Check if Abstract Class suits your needs:
PHP: Class Abstraction
class Child extends Parent {
public function parentMethod(
# Code
}
}
Abstract class Parent {
abstract public function parentMethod();
}
First of all I'm very new to OOP and I'm struggling big time. I have a question about the current design of my application and inheritance.
I have a bootstrapper file which initiates all my core classes, after including them, like this:
$security = new Security;
$error_handler = new ErrorHandler;
$application = new Application;
$mysql = new MySQL;
$template = new Template;
$user = new User;
I load the Security and ErrorHandler class first because the Application class needs them first (throw custom 404 errors, make GET variables safe etc). Now all classes extend the Application class, but I can't seem to call any data in any class from a child or parent class.
I read that I need to call the constructor of the parent class first to use any data. That's not really sexy and usefull in my eyes and I don't really see the use of using extends then.
Should I change the design? Or how could I use data from one to another class? I already tried composition but that ended up in a nightmare because I couldn't use any data of different child classes at all.
This is a weird set-up anyhow. You definitely should NOT be using some bootstrapper functionality to preload your classes, especially if certain classes have finite dependencies on other classes. What would be a bit better is this:
Your Security and ErrorHandler classes should use either static methods to allow their functionality to be used without declaring the class OR they should be created as a class var of the Application class.
class Security {
// can be invoked anywhere using Security::somefunction('blah');
public static somefunction($somevar) { ... }
}
OR
require_once('security.php');
require_once('errorhandler.php');
class Application {
public $security;
public $errorHandler;
public function __construct() {
$this->security = new Security;
$this->errorHandler = new ErrorHandler;
}
}
I'm not sure what you mean when you say that you can't access data from any class. Classes should naturally inherit any variables and functions that their parents have declared. So for example:
require_once('application.php');
class User extends Application {
public function throwError($message) {
return $this->errorHandler->somefunction($message);
}
}
Without expressly declaring $this->errorHandler from within the User class, this should still work, as the $errorHandler class var is declared in the Application class.
If you have a child-class that defines a __construct() method, and want its parent's __construct() method to be called, the __construct() method of the child class must call the parent's one.
That's the way it is in PHP ; that's what you must do ; not much of a choice.
As a reference, quoting the Constructors and Destructors section of the manual :
Parent constructors are not called
implicitly if the child class defines
a constructor. In order to run a
parent constructor, a call to
parent::__construct() within the
child constructor is required.
Sorry for constantly re-editing my question but looks like this is the only way to ask it properly.
My original problem is the following pseudo-code (a controller and it's parent) isn't working as i would like to:
class Parent {
var $data = array();
public function __construct( OtherClass $otherClass ) {
$this->data = $otherClass->getData(); //contains some => thing
$this->init($otherClass->getClassName());
}
public function init( $className ) {
new $className; //new Child
}
public function __get( $name ) {
return array_key_exists($name, $this->data) ? $this->data[$name] : null;
}
}
class Child extends Parent {
public function __construct() {
echo $this->some; //won't return 'thing';
}
}
fireeyedboy helped me a lot (thank you) and pointed out Zend_Controller_Action is doing what i want but i can't understand how they do it?
Original question
I know there was some similar questions here but i cannot dump them. Also i know i can reverse the whole process so i can initialize Child first then call parent::__construct but this seems unwanted for me. How can i access Parent variables easily in my case?
Update:
Let me clarify a little bit. Child is an arbitrary controller. Parent is the mother of all controllers. Many frameworks are doing the same but controllers can utilize their parent controllers variables, methods or objects without calling parent::__construct (and therefore filling child class constructors with unnecessary arguments). I don't like to rewrite any of these frameworks but i'd like to understand how they're operating.
Your child class doesn't call parent constructor. Here's a fix:
class Child extends Parent {
public function __construct() {
parent::__construct();
echo $this->some;
}
}
Update: Parent classes' constructors aren't called automatically in PHP. See the documentation:
Note: Parent constructors are not
called implicitly if the child class
defines a constructor. In order to run
a parent constructor, a call to
parent::__construct() within the child
constructor is required.
So what you're asking does not happen. Either you have misinterpreted the class structure or how they operate. Note that PHP also supports legacy constructor naming (at least until 5.3.3): If there is no __construct() method in a class, PHP assumes the constructor is named after the class (ie. class Foo { function Foo() {}) treats the Foo() method as constructor).
Injecting ANYTHING using controller's construct is generally a BAD PRACTICE! Problem lies in your design. What kind of object is OtherClass? Is it DB adapter? Is it ACL? Is it some helper class?
If you need external class in your controller I suggest using action helpers. That's what they are created for ;) Or create an action helper that will fetch this OtherClass from somewhere when needed.
You should NEVER use __construct() to do any of your dirty work. That's what init() is used for. But it has no params. And there is a reason for that - again - you should not inject dependencies like this ;)
Update:
Note your class uses discouraged PHP4 member variable definition syntax. Try replacing your var with protected.
The problem is that your Child class does not call the base constructor.
Incidentally, Parent is not a valid class name in PHP. I have changed the class names for clarity. See below:
class ChildClass extends ParentClass {
public function __construct() {
parent::__construct(/* what goes here? */);
echo $this->some;
}
}
However, note the what goes here? part: your base class requires a reference to an OtherClass instance to be constructed. Therefore, since ChildClass IS-A ParentClass, it also needs to get such an instance somehow. You will need to either add a parameter to ChildClass::__construct and forward the value to parent::__construct, or somehow figure out a default value yourself.