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();
}
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 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
I am new to PHP and just get into OOP. I have few generic methods used to set and get properties. I use them quite often in almost all the classes, i put those methods in a class and extends other classes from it. Now i can access the methods from child class but dont know how set and get attributes of child class through them ... parent class base.php
class Base
{
public function __construct()
{
}
function __set($propName, $propValue)
{
$this->$propName = $propValue;
}
function setProperties(array $data)
{
foreach($data as $propName => $propValue)
$this->$propName = $propValue;
}
function __get($propName)
{
return (isset($this->$propName))? $this->$propName : "Invalid property!";
}
function getProperties(array $properties)
{
foreach($properties as $propName)
$propVals[$propName] = $this->$propName;
return $propVals;
}
}
child class categories.php
class categories extends Base
{
private $id;
private $pid;
private $title;
private $status;
public function __construct()
{
parent::__construct();
}
}
and i called it like
$objCat = new categories();
$objCat->setProperties(array('id'=>'10', 'pid'=>'6'));
print_r( $objCat->getProperties(array('id', 'pid')));
Need little guidance here. If its the right way? or at least is it possible to do it like this? if so how to accomplish this ...
thanks
Extending a class is something you only want to do when you can say class categories is a class Base. Something like that sort of utility class you have their is almost always the wrong way to go. PHP also has introduced something called traits for copy/paste code. However my personal preference is that it is something you will never want to use, because it tightly couples the traits to your class, which is something you want to avoid.
See for more information the Liskov Substitution principle in SOLID programming.
If it was up to me I would avoid those magic getters / setters either way and just add your own getters / setters methods to the class.
The mistake about some base class isn't something only you are doing (hell even I have done it in the past). Think about some class Database and a class Article. Because the Article class needs access to the database many people let the class extend the Database class. This isn't correct because an article isn't an database. Instead an instance of the database class should be injected into the article class by using dependency injection. The instance should either be injected into the class constructor (if all or many methods need access to it) or just the methods that need it. So when extending a class you have to be able to say class B is a class A.
Some other notes about your code:
Always make your class names PascalCase. This is not really required to make your code work, but it follows a naming convention often used.
And my personal preference a bit: please always add curly braces to your foreach statements. It is more clear what is happening when other people are reading your code.
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.
If I have this class:
<?php
class Model
{
var $db;
function Model()
{
$this->db=new Db_Class();
}
}
?>
and a second class that extended the parent class:
<?php
class LessonModel extends Model
{
public function LessonModel()
{
//code here
}
public function getTitle($id)
{
$this->db->setTable('myTable');
return $this->db->get('title',$id);
}
}
?>
Is it safe to assume that the $LessonModel->db field would have been instantiated by the parent Model class's constructor, or do I need to run it manually using something like parent::Model();?
You cannot assume that the parent constructor has been called because you have overridden this in your subclass. You would need to call parent::Model() as you suggest. If you change the class you are inheriting from you would obviously need to change this.
If you are using PHP5 then you can name your constructors __construct(). This has the benefit of letting you easily call a parent constructor by doing parent::__construct() in any derived class without specifying the parent class name. You can then rearrange your classes' inheritance with less hassle and less danger of introducing obscure bugs.
In the given example, you can assume that.
However, if your child class defines a constructor, PHP will not implicitly call it's parent constructor.
In order to do that, call:
parent::__construct();
There's a cheap way to get around having to call the parent constructor.
Create an empty init() method in the base class. Call $this->init() in the base class constructor.
All sub-classes can implement init() if they want to run code when the class is created.