I have parent and child classes as follows:
abstract class ParentObj {
private $data;
public function __construct(){
$this->data = array(1,2,3);
var_dump($this->data);
$this->method();
}
public function method(){
echo "ParentObj::method()";
}
}
class ChildObj extends ParentObj {
public function __construct(){
parent::__construct();
var_dump($this->data);
}
public function method(){
echo "ChildObj::method()";
}
}
The expected output:
array(1,2,3)
ChildObj::method()
array(1,2,3)
The actual output:
array(1,2,3)
ParentObj::method()
NULL
The problem is, the child object cannot access the data property and the parent refuses to call the overridden method in the child.
Am I doing something wrong, or does anybody have any ideas?
EDIT: I should clarify that I am instantiating a ChildObj as $child = new ChildObj()
You've declared data as private, so ChildObj won't be able to access it - you need to make it protected instead:
protected $data;
My PHP (5.2.8) prints ChildObj::method() - are you running an older version?
Ok, the problem was the methods were actually declared private, not public as in my post, thus suffering the same symptom as the $data property.
Related
I am building an MVC component and I'm getting stuck with an issue with a parent and child model. I have a few methods in the parent Model and they're not working with the database_class object
the constructor works fine
but when I use that object in the methods its like the constructor doesn't exist?
Class Controlller
{
public function __construct()
{
$this->childModel = $this->model('childModel');
} // end construct
// methods go here
}
Here are the models:
class childModel extends parentModel {
private $dbo;
public function __construct()
{
$dbobj = new Database_class;
$this->dbo = $dbobj;
}
//methods
}
class parentModel {
private $dbom;
public function __construct()
{
$dbombj = new Database_class;
$this->dbom = $dbombj;
var_dump($this->dbom); //working perfectly as database object
}
public function methodName()
{
var_dump($this->dbom); //not showing up as database object
}
}
I don't think this code is doing what you think it's doing. In childModel, you are overwriting the __construct method of the parentModel, so the __construct in the parentModel never gets called. Therefore $this->dbom should be null. Furthermore if you wish to use $this->dbom from the childModel, you should probably change the scope from private $dbom to protected $dbom. See this page for more info on that: http://php.net/manual/en/language.oop5.visibility.php
I have a protected function that is defined within a certain class. I want to be able to call this protected function outside of the class within another function. Is this possible and if so how may I achieve it
class cExample{
protected function funExample(){
//functional code goes here
return $someVar
}//end of function
}//end of class
function outsideFunction(){
//Calls funExample();
}
Technically, it is possible to invoke private and protected methods using the reflection API. However, 99% of the time doing so is a really bad idea. If you can modify the class, then the correct solution is probably to just make the method public. After all, if you need to access it outside the class, that defeats the point of marking it protected.
Here's a quick reflection example, in case this is one of the very few situations where it's really necessary:
<?php
class foo {
protected function bar($param){
echo $param;
}
}
$r = new ReflectionMethod('foo', 'bar');
$r->setAccessible(true);
$r->invoke(new foo(), "Hello World");
That's the point of OOP - encapsulation:
Private
Only can be used inside the class. Not inherited by child classes.
Protected
Only can be used inside the class and child classes. Inherited by child classes.
Public
Can be used anywhere. Inherited by child classes.
If you still want to trigger that function outside, you can declare a public method that triggers your protected method:
protected function b(){
}
public function a(){
$this->b() ;
//etc
}
If the parent's method is protected, you can use an anonymous class:
class Foo {
protected function do_foo() {
return 'Foo!';
}
}
$bar = new class extends Foo {
public function do_foo() {
return parent::do_foo();
}
}
$bar->do_foo(); // "Foo!"
https://www.php.net/manual/en/language.oop5.anonymous.php
You can override this class with another where you make this public.
class cExample2 extends cExample {
public function funExample(){
return parent::funExample()
}
}
(note this won't work with private members)
But the idea of private and protected members is to NOT BE called from outside.
Another option (PHP 7.4)
<?php
class cExample {
protected function funExample(){
return 'it works!';
}
}
$example = new cExample();
$result = Closure::bind(
fn ($class) => $class->funExample(), null, get_class($example)
)($example);
echo $result; // it works!
If you want to share code between your classes you can use traits, but it depends how you want use your function/method.
Anyway
trait cTrait{
public function myFunction() {
$this->funExample();
}
}
class cExample{
use cTrait;
protected function funExample() {
//functional code goes here
return $someVar
}//end of function
}//end of class
$object = new cExample();
$object->myFunction();
This will work, but keep in mind that you don't know what your class is made of this way. If you change the trait then all of your classes which use it will be altered as well. It's also good practice to write an interface for every trait you use.
here i can give you one example like below
<?php
class dog {
public $Name;
private function getName() {
return $this->Name;
}
}
class poodle extends dog {
public function bark() {
print "'Woof', says " . $this->getName();
}
}
$poppy = new poodle;
$poppy->Name = "Poppy";
$poppy->bark();
?>
or one another way to use with latest php
In PHP you can do this using Reflections. To invoke protected or private methods use the setAccessible() method http://php.net/reflectionmethod.setaccessible (just set it to TRUE)
I am using Laravel. i was facing issue while access protected method outside of class.
$bookingPriceDetails = new class extends BookingController {
public function quotesPrice( $req , $selectedFranchise) {
return parent::quotesPrice($req , $selectedFranchise);
}
};
return $bookingPriceDetails->quotesPrice($request , selectedFranchisees());
here BookingController is Class name from which i want to get protected method. quotesPrice( $req , $selectedFranchise) is method that i want to access in different Class.
A parent class is constructed from outside the child class, thus, it's constructor cannot be called from inside the child. How should one go about accessing properties of the parent from the child in this case.
Example:
class MyParent {
protected $args;
protected $child;
public function MyParent($args=false){
$this->args=$args;
$this->child=new MyChild();
}
public function main(){
$this->child->printArgs();
}
}
class MyChild extends MyParent{
public function MyChild(){}
public function printArgs(){
Echo "args: ".$this->args['key']." = ".$this->args['value']."\n";
}
}
$parent=new MyParent(array('key'=>'value'));
$parent->main();
Empty variables are returned when run:
jgalley#jgalley-debian:~/code/otest$ php run.php
args: =
__construct() is the constructor. You are using a variant from ancient PHP4-times.
You instanciate two completely different objects, therefore of course the property $args is completely independent.
abstract class MyParent {
protected $args;
public function __construct($args=false){
$this->args=$args;
}
public function main(){
$this->printArgs();
}
abstract public function printArgs();
}
class MyChild extends MyParent{
public function printArgs(){
Echo "args: ".$this->args['key']." = ".$this->args['value']."\n";
}
}
$$object=new MyChild(array('key'=>'value'));
$object->main();
This at least works, but a problem is, that I don't know exactly what are the design goals. Because it seems to be a kind of cli-Application you should have a look at existing solutions to get an idea, how it could get solved.
I am trying to create a simple MVC my personal use and I could really use an answer to this simple question
class theParent extends grandParent{
protected $hello = "Hello World";
public function __construct() {
parent::__construct();
}
public function route_to($where) {
call_user_func(array("Child", $where), $this);
}
}
class Child extends theParent {
public function __construct() {
parent::__construct();
}
public function index($var) {
echo $this->hello;
}
}
$x = new theParent();
$x->route_to('index');
Now Child::index() this throws a fatal error: Using $this when not in object context but if I were to use echo $var->hello, it works just fine.
I know I can use $var to access all properties in the parent, but I would rather use $this.
By writing call_user_func(array("Child", $where), $this) you are calling the method statically. But as your method isn't static you need some kind of object instance:
call_user_func(array(new Child, $where), $this);
Documentation on callback functions.
You don't have an instance of Child to call a non-static method upon when you're doing $x->route_to('index'); The way you're calling the method, without having made an instance first, is implied static.
There are two ways to correct it. Either make the Child class's methods static:
class Child extends theParent {
public function __construct() {
parent::__construct();
}
static public function index($var) {
echo self::$hello;
}
}
...or make an instance of the child class for the parent to use:
class theParent extends grandParent{
protected $hello = "Hello World";
private $child = false
public function __construct() {
parent::__construct();
}
public function route_to($where) {
if ($this->child == false)
$this->child = new Child();
call_user_func(array($this->child, $where), $this);
}
}
Of course, both of these samples are rather generic and useless, but you see the concept at hand.
$this gives you access to everything visible/accessible in the current object. That can either be in the class itself (this) or any of it's parents public or protected members/functions.
In case the current class overrides something of a parent class, you can access the parent method explicitly using the parent keyword/label, whereas you add :: to it regardless if it is not a static method.
Protected variables exist only once, so you can not use parent to access them.
Is this info of use?
I want to be able to set a private attribute's value in the parent constructor, and call the value in a child's constructor or method.
For example:
<?php
abstract class MainClass
{
private $prop_1;
private $prop_2;
function __construct()
{
$this->prop_2 = 'this is the "prop_2" property';
}
}
class SubClass extends MainClass
{
function __construct()
{
parent::__construct();
$this->prop_1 = 'this is the "prop_1" property';
}
public function GetBothProperties()
{
return array($this->prop_1, $this->prop_2);
}
}
$subclass = new SubClass();
print_r($subclass->GetBothProperties());
?>
Output:
Array
(
[0] => this is the "prop_1" property
[1] =>
)
However, if I change prop_2 to protected, the output will be:
Array
(
[0] => this is the "prop_1" property
[1] => this is the "prop_2" property
)
I have basic knowledge of OO and php, but I can't figure out what is preventing prop_2 from being called (or shown?) when it's private; it can't be a private/public/protected issue, since 'prop_1' is private and able to be called and shown... right?
Is it an issue of assigning the values in the child class vs parent class?
I would appreciate help in understanding why.
Thank you.
Private properties of parent class can not be accessed in Child class and vice versa.
You can do like this
abstract class MainClass
{
private $prop_1;
private $prop_2;
function __construct()
{
$this->prop_2 = 'this is the "prop_2" property';
}
protected function set($name, $value)
{
$this->$name = $value;
}
protected function get($name)
{
return $this->$name;
}
}
class SubClass extends MainClass
{
function __construct()
{
parent::__construct();
$this->set('prop_1','this is the "prop_1" property');
}
public function GetBothProperties()
{
return array($this->get('prop_1'), $this->get('prop_2'));
}
}
If you want to access the parent's properties from the child class, you must make the parent's properties protected NOT private. This way they are still inaccessible externally.
You can't override the parent's private properties visibility in the child class in the way you are trying to.
As others have noted, you'd need to change the parent's properties to protected. However, the other way is by implementing a get method for your parent class, which allows you access to the property, or implementing a set method if you want the ability to over-ride it.
So, in your parent class, you'd declare:
protected function setProp1( $val ) {
$this->prop_1 = $val;
}
protected function getProp1() {
return $this->prop_1;
}
Then, in your child class, you can access $this->setProp1("someval"); and $val = $this->getProp1(), respectively.
There is a simple trick you an use with lambdas, which I found here: https://www.reddit.com/r/PHP/comments/32x01v/access_private_properties_and_methods_in_php_7/
basically you use a lambda and bind it to the instance and then you can access it's private methods and properties
Info on the lambda call: https://www.php.net/manual/en/closure.call.php