I am really sorry if this is s dumb question and I'm having a brain fart, this just seems like something I should know. If I have a structure similar to below, is there some way to get $fooVar in Class bar. Do I need to find some way to pass $fooVar as a parameter or is there some inheritance there that I can take advantage of? I'd like to avoid passing it as a parameter if at all possible. Class bar extends another class and if I passed t as a parameter I'd have to do some extra work.
Thanks so much for your help.
Class foo{
$fooVar;
$bar = new bar()
}//end foo{}
Class bar extends AnotherClass{
echo $foo->fooVar;
}//end bar{}
First of all I want to say, I just know a bit about php but I think this problem can be adapted to any other OOP based language. So I tried to put some code for you up. Their are 4 different approaches I am aware of. (I want to consider that I didn't test the below code snippets.)
Declare a get-Function
in your superclass to access the value of $fooVar. This has the positiv effect to access the value from any other class which can call the get-function.
Like this:
Class foo{
private $fooVar;
function __construct() {
$bar = new bar();
}
function getFooVar() {
return $fooVar;
}
}
Class bar extends foo{
function __construct() {
private $foo = parent::getFooVar(); //init $foo on instantiation by get-function
}
}
2.
Declare $fooVar as protected
the make $fooVar only accessible by their subclasses.
Class foo{
protected $fooVar;
function __construct() {
$bar = new bar();
}
}
Class bar extends foo{
function __construct() {
private $foo = parent::$fooVar; //init $foo on instantiation by parent
}
}
3. Add $fooVar as parameter
to your subclass constructor. (I am fully aware of that this is not what you want, but I state it here as another solution and for clarification.)
Class foo{
protected $fooVar;
function __construct() {
$bar = new bar($fooVar);
}
}
Class bar extends foo{
function __construct($var) {
private $foo = $var; //init $foo on instantiation with parameter
}
}
4.
Make $fooVar global.
(another solution but not recommanded.)
I think you are going well with the get function. From the last two cases I would advice especially against the last one.
I really hope this is what you are looking for and it helps alot.
Related
I have a DB interface object, DBI, that requires authentication. I have an object, foo, that doesn't extend anything. I also have a class bar that extends the DBobject If I have an instance of foo that is a member of bar thus:
$b->$f=new foo;
How can I call somefunction() in $b from a function inside the foo class? I've tried making the somefunction() static, but I don't want the authentication info sprinkled throughout my code. And if I try having foo extend the DBI or bar classes, I wind up with an issue including the files and my foo __construct function fails because the bar class is not found. Is there another construct similar to extends/parent:: that I can use with objects that are just instances amongst each other?
The way that I've done this in the past, is create the Foo object within the Bar object within the __construct(). Then utilize the __call magic method to intercept the methods and see where it is. So the code could look something like this:
public function __call($sMethod, $aArgs) {
if(method_exists($this, $sMethod){
return call_user_func_array(array($this, $sMethod), $aArgs);
}
} elseif(method_exists($this->foo, $sMethod)) {
return call_user_func_array(array($this->foo, $sMethod), $aArgs);
}
}
public function __construct() {
$this->foo = new foo();
}
Then you can call the functions from either foo or bar, even though they are not extended. Just a though, maybe there is an easier way to do this.
** EDIT **
The benefit to this is you don't need to specify whether or not you are calling a method from foo or from bar, they will just "work".
** EDIT **
Based on the comments, you want to do this, correct? Because based on the code below, if you run it it works correctly.
class foobar {
public function test() {
echo 'This is a test';
}
}
class foo extends foobar {
}
class bar {
}
$bar = new bar();
$bar->foo = new foo();
$bar->foo->test();
or the alternative:
class foobar {
public function test() {
echo 'This is a test';
}
}
class foo extends foobar {
}
class bar {
public function testFooBar() {
$this->foo->test();
}
}
$bar = new bar();
$bar->foo = new foo();
$bar->testFooBar();
Both work at long as you know the property name you are setting for the object.
In addition to call_user_func and call_user_func_array, if you want to access methods and properties of the container object (not parent class), you need a reference to it. Here is a similar post.
I'm wondering why the following code won't print out anything. I'm trying to access Bar::$some_var from method in parent class. Where Bar::$some_var is defined in it's constructor.
I've tried using self::$some_var and static::$some_var in Foo::hello() but neither worked. Do I have to make $some_var static?
class Foo {
private $some_var;
public function __construct() {
$this->some_var = 5;
}
public function hello() {
print $this->some_var;
}
}
class Bar extends Foo {
public function __construct() {
$this->some_var = 10;
}
}
$bar = new Bar();
$bar->hello();
Thanks in advance.
private makes a member variable unavailable outside of a class. You need to use protected to allow extending classes to have access to that variable.
protected $some_var;
See Visibility
Your class variable cannot be private if you would like your child class to access it.
Try protected instead and it should work!
:: operator is used to access class items (constants, static
variables, static methods)
-> operator is used to access object items (non static properties and methods)
anyway in your code the problem is visibility of $some_var. It has to be almost protected, public will also work
I am trying to extend a PHP class without rewriting the whole thing. Here is an example:
<?
$a = new foo();
print $a->xxx();
$b = new bar();
print $b->xxx();
class foo {
const something = 10;
public function xxx() {
$this->setSomething();
return $this->something;
}
private function setSomething() {
$this->something = self::something;
}
}
class bar extends foo {
public function xxx() {
$this->setSomething();
$this->something++;
return $this->something;
}
}
?>
However when I run the script I get the following error:
Fatal error: Call to private method foo::setSomething() from context 'bar' in test.php on line 23
It would seem that bar is not inheriting the private function setSomething(). How would I fix this without modifying the foo class?
No, you can not fix this without modifying the foo class. Because an inherited class can not access parent class's private members. It's a very basic oop rule.
Declare setSomething() as protected. It'll be solved.
See manual
Private members are not inheritable, you can not use them in sub class. They are not accessible outside the class.
You must need to make that function as protected or public. Protected members are accessible to that class and for the inherited class. So, your best bet is to make that function Protected.
bar is inheriting the function alright, but it can't call it. That's the whole point of private methods, only the declaring class can call them.
Try reflection
http://php.net/manual/en/class.reflectionclass.php
Also:
Call private methods and private properties from outside a class in PHP
Did you try this?
class bar extends foo {
public function xxx() {
$this->something = parent::xxx();
$this->something++;
return $this->something;
}
}
Note the parent::xxx(); is public, so it should work... even though it looks like a static call.
Without modifying the original class, there is no way for the inherited class to directly call private methods of the parent class.
abstract class Mother {
protected static $foo = null;
protected static $bar = null;
public function getFoo() { return static::$foo; }
public function getBar() { return static::$bar; }
public function setFoo($foo) { static::$foo = $foo; }
public function setBar($bar) { static::$bar = $bar; }
}
class Brother extends Mother {
protected static $foo = 'BROTHERS';
}
class Sister extends Mother {
protected static $foo = 'SISTERS';
}
$brother1 = new Brother();
$brother2 = new Brother();
$sister1 = new Sister();
$sister2 = new Sister();
$sister1->setBar('ONLY SISTERS'); // We set $bar = 'ONLY SISTERS' at sister1.
// We want only Sister instances to get this value...
// however Brother instances also get this value!
echo '<p>Brother 1: Foo="'.$brother1->getFoo().'", Bar="'.$brother1->getBar().'"</p>';
// Foo="BROTHERS", Bar="ONLY SISTERS"
echo '<p>Brother 2: Foo="'.$brother2->getFoo().'", Bar="'.$brother2->getBar().'"</p>';
// Foo="BROTHERS", Bar="ONLY SISTERS"
echo '<p>Sister 1: Foo="'.$sister1->getFoo().'", Bar="'.$sister1->getBar().'"</p>';
// Foo="SISTERS", Bar="ONLY SISTERS"
echo '<p>Sister 2: Foo="'.$sister2->getFoo().'", Bar="'.$sister2->getBar().'"</p>';
// Foo="SISTERS", Bar="ONLY SISTERS"
So apparently if static::$bar is not explicitly redefined in every child (Brother, Sister) their parent (Mother) will set the value for them (or at least for those who did not redefine it).
The question: Is there any way to prevent children who did not redefine static::$bar from receiving the new value? In other words, how to make sure only the referred class gets a new value, EVEN if static::$bar is not explicitly redefined in every child?
No, not the way you're doing it. That's what private scope is for. Child classes inherit all public and protected static properties--which mean they all point to the same value whether they are a parent, child, or sibling.
This is correct and good OO.
You should define the variable it as private static in the parent class and then the child wouldn't be able to see it directly and could create their own private static variable with the same name if needed.
Provide static getters and setters in your class to access the private static property.
Brother::getFoo();
Sister::getFoo();
You can make the getFoo() in the parent class Mother abstract or not, if you need to access it directly make it non-abstract so you can do:
Mother::getFoo();
This is just madness.
You should understand that extend defines IS A relationship. For example : class Duck extends Bird{} this means that every instance of Duck is a Bird.
So in your example, every Brother is a Mother. I fail to see how this would make a sense.
And the other thing : why the hell are you abusing static variables? What you are doing there is not object oriented programming. You are just wrapping global scope variables and functions in a namespace ( which happens to look like class ).
Some additional links on the subject, you might find useful:
static considered harmful
performance of static methods vs functions
clean code talks: global state and singletons
drawbacks of statuc methonds in php
I am having problems creating a variable with data from another class. Here is what I am doing...
<?PHP
class Customers extends Controller {
private $foo = $this->session->userdata('foo');
}
You probably want something more like this:
class Customers extends Controller
{
private $foo;
public function __construct()
{
parent::__construct();
$this->foo = $this->session->userdata('foo');
}
}
It's hard to know for sure without knowing more about your project.
You can set it with constructor because you are inhering from parent class:
class Customers extends Controller {
private $foo = null;
function __construct(){
parent::__construct();
$this->foo = $this->session->userdata('foo');
}
}
This is not possible: $this doesn't exist at the moment when you define the class, and you can't call functions at all at this point at all.
You will need to assign $foo in the constructor, after $this->session has been initialized. (#konforce beat me to the example.)