So I'd like to be able to call a method of an object from a created object as deep as I'd like.
For example
$test = new sampleObject;
$test2 = $test->createChild();
$test3 = $test2->createChild();
...
catch is, I need to be able to refer to a method from the topmost creator class.
so I have my main class
class sampleObject
{
public $tons, $of, $properties;
public function createChild()
{
$someVar = new childObject();
$this->otherMethod();
return $someVar();
}
public function otherMethod()
{
//Do some stuff
}
}
class childObject
{
public $child, $properties;
function createChild()
{
$someVar = new childObject();
//here is my issue
//I need to call a otherMethod from the creating class here but not static .
return $someVar;
}
}
Is this the wrong approach or is there a way to reference that creating class object.
I'd like to keep the created object's properties secluded from the creator class.
I thought about just passing the object, but I'd like to keep the same structure if possible as the creator class.
The best way I could find to do this was to pass the object that it is a part of to the sub-object.
so $test2 = $test->createChild($test);
and
class childObject
{
public $child, $properties, $parent;
function createChild()
{
$someVar = new childObject($parent);
$this->parent = $parent;
//here is my issue
//I need to call a otherMethod from the creating class here but not static .
return $someVar;
}
}
Related
could someone explain how to use not static property in static method in php, this is wrong code, but i want to know how to fix this, thank you
<?php
class SomeClass
{
public $_someMember;
public function __construct()
{
$this->_someMember = 1;
}
public static function getSomethingStatic()
{
return $this->_someMember * 5; // here's the catch
}
}
echo SomeClass::getSomethingStatic();
?>
You can't directly. You need to create an object instance. You can make one and pass it to a static method, or make one in static method's body.
Regular (non-static) properties require object instance of given class (type).
Static methods are called by referring to the class itself, not an object.
You can however use static properties or constants for static methods needs without creating object instance at all.
You have to instantiate object
<?php
class SomeClass
{
public $_someMember;
public function __construct()
{
$this->_someMember = 1;
}
public static function getSomethingStatic()
{
$object = new self();
return $object->_someMember * 5; // here's the catch
}
}
echo SomeClass::getSomethingStatic();
You can statically create an instance of the class that the method is being called on via:
$instance = new static();
You can also statically create instances of the class that actually defines the method via:
$instance = new self();
As an example, take these classes First and Second.
class First
{
public static function getStatic()
{
return new static();
}
public static function getSelf()
{
return new self();
}
}
class Second extends First{ }
When we use Second::getStatic(), we will get an instance of Second.
When we use Second::getSelf(), we will get an instance of First.
When we call either method via First, we will get an instance of First.
This means you can change your method to:
public static function getSomethingStatic()
{
$instance = new static(); // or new self() if you always want to use 'SomeClass'
// and never an extending class.
return $instance->_someMember;
}
I have a parent class that depends on whether child class are instantiated.
class GoogleApp {
protected $auth_token;
public function __construct($scopes) {
$this->auth_token = $scopes;
}
}
class Gmail extends GoogleApp {
public function __construct() {
print_r($this->auth_token);
}
}
$googleApp = new GoogleApp('gmail'); // Change the actual class for all child instances
$gmail = new Gmail();
The idea is that all the children use the same auth_token (which is generated on whether the child classes are used - as of now, I'm just manually adding them to whether I included them in my code). Since I have quite a few child classes (like Calendar or Drive), do I have to inject the parent into each child instance or is there an easier way?
If I understand your request correctly, you're pretty close, you just need to declare your property as static.
class FooParent
{
protected static $scope = null;
public function __construct($scope)
{
self::$scope = $scope;
}
public function getScope()
{
return self::$scope;
}
}
class FooChild extends FooParent
{
public function __construct()
{
if (self::$scope === null) {
throw new Exception('Must set scope first.');
}
}
}
$parent = new FooParent('foo');
$child = new FooChild();
echo $child->getScope(), "\n"; // prints "foo"
Basically this is what i want to do:
<?php
class App {
public $var = "main-class";
public function load() {
$this->var = "child-class";
$child = new Child;
$child->echo_var();
}
}
class Child extends App {
public function echo_var() {
echo $this->var;
}
}
$app = new Child;
$app->load();
?>
It outputs "main-class", i want it to output "child-class" without having to modify the child class (because i want it to be sort of a "clean" and dynamic class).
I accept suggestions for another course of action
PS: This is part of an Small MVC Framework i'm trying to develop.
There are two ways that you could do this. Both are going to need to use constructors. With the first one, the child will declare itself when created
<?php
class App {
public $var = "main-class";
public function __construct($var=null) {
if($var !== null) {
$this->var = $var;
}
}
public function load() {
$child = new Child ();
$child->echo_var();
}
}
class Child extends App {
public function __construct(){
parent::__construct("child-class");
}
public function echo_var() {
echo $this->var;
}
}
$app = new Child();
$app->load();
?>
The second one allows the parent to declare the name of the child.
<?php
class App {
public $var = "main-class";
public function __construct($var=null) {
if($var !== null) {
$this->var = $var;
}
}
public function load() {
$child = new Child ("child-class");
$child->echo_var();
}
}
class Child extends App {
public function echo_var() {
echo $this->var;
}
}
$app = new Child();
$app->load();
?>
Both of those examples work and do what you want, I believe.
This isn't how inheritance works - By creating a new Child object, its data members are all initialized with their default values. When you do $this->var = "" in the parent class, you're setting the data members for the $app object, not the $child object.
You can modify the child class to incorporate a constructor that accepts parameters, and that constructor would set its data members properly. To achieve something similar to what you want, you can use constructors:
<?php
class App {
public $var = "main-class";
public function __construct() {
$this->var = "child-class";
}
public function load() {
$child = new Child;
$child->echo_var();
}
}
class Child extends App {
public function __construct()
{
parent::__construct();
}
public function echo_var() {
echo $this->var;
}
}
$app = new App;
$app->load();
I find it very strange that your parent class instanciates it's child. Generally, you would instanciate the child, and you get all the functionality of the parent.
$app = new Child();
$app->load();
The problem is that you actually have 2 different instanciations. You have an object of App and it's holding a separate object of Child.
The other way to do this would be to make $var a static variable and then it would be available independent of the instantiation. I don't generally recommend making properties static though. It's generally considered bad form (for numerous reasons).
How do I use an object (along with its methods and properties) when I'm inside an object?
Say I have useless classes like these:
class Fruit {
private $name; // Name of the fruit.
private $health = 10; // 0 is eaten, 10 is uneaten.
private $object; // This is a PHP object.
public function __construct($name) {
$this->name = $name;
}
public function set($varname,$value) {
$this->$varname = $value;
}
}
class Eater {
private $name;
public function eat($object) {
$object->set('health',0); // I know I can pass and modify objects like this.
// The object is passed by reference in PHP5 (but not 4), right?
}
}
And I use it as such:
<?php
$pear = new Fruit("Pear");
$apple = new Fruit("Apple");
$paul = new Eater("Paul");
$paul->eat($apple);
?>
But if I modify the Eater class like so:
class Eater {
private $name;
private $objectToEat; // Let's say if I need the object to be over here instead of in a method.
public function set($varname,$value) {
$this->$varname = $value;
}
public function eat() {
$this->objectToEat->set('health',0); // This doesn't work!
}
}
And set the main program like so:
<?php
$pear = new Fruit("Pear");
$apple = new Fruit("Apple");
$paul = new Eater("Paul");
$paul->set('objectToEat',$apple);
$paul->eat();
?>
How can I access the object's properties from inside a method? I know I use $this->objectToEat to tell PHP I'm talking about the class properity, but since that property is an object, how do I access the object's methods?
I've tried $this->objectToEat->set('health',0) but that doesn't work. I hope you guys understand what I'm trying to get at (sorry, I can't figure out how to condense my question without compromising clarity)!
You have to set the property correctly. Since it's private, you can't do this from outside the object, so you have to use encapsulation:
class Eaters {
private $name;
private $objectToEat;
public function eat() {
$this->objectToEat->set('health',0); // Assumed "object" was just a typo
}
public function setObjectToEat($object) {
$this->objectToEat = $object;
}
}
Then use it like so:
<?php
$pear = new Fruit("Pear");
$apple = new Fruit("Apple");
$paul = new Eater("Paul");
$paul->setObjectToEat($apple);
$paul->eat();
?>
Note: In this brief example, your original method is a better design. In certain cases, you might want to prime the method to be used by setting properties beforehand, but more often you want to call it with parameters directly, since it's more clear and more reusable (compartmentalized).
This answer modifies Renesis' answer
In the class, the object to eat is a private variable hence you can't go
$paul->objectToEat = $apple;
What you can do is to make a setter method inside Eaters
class Eaters {
private $name;
private $objectToEat;
public function eat() {
$this->objectToEat->set('health',0); // Assumed "object" was just a typo
}
public function setFood($object) {
$this->objectToEat = $object;
}
}
Therefore, you can call the setFood() method instead.
OR
Change eat() to
public function eat($object) {
$this->object->set('health',0);
return $object;
}
Saving the modified object back to the original variable.
OR
class Eaters {
private $name;
public function eat(&$object) { // this passes object by reference
$object->set('health', 0);
}
}
Although this code is not tested, that is how you can pass a variable by reference.
NOTE: You only need the & when defining the method not when you're passing an argument. For more info about Passing by Reference go to this link
It's probably because your eat method isn't accepting any parameters, and the Eaters class has no $object property.
Can you make $objectToEat a reference and then use it as such in the eat() function?
you have to set $this->object in class Eaters
function __construct($object){
$this->object = $object;
}
or
<?php
$pear = new Fruit("Pear");
$apple = new Fruit("Apple");
$paul = new Eater("Paul");
$paul->eat($apple);
?>
class Tester {
private $variable;
private $anObj;
public function testFn($val) {
$this->variable = $val;
$this->anObj = new SecondObj();
$this->doSomething();
}
public function doSomething() {
echo("My variable is set to " . $this->variable);
$this->anObj->wow();
}
}
class SecondObj {
public function __construct() {
echo("I'm new!");
}
public function wow() { echo("Wow!"); }
}
$tester = new Tester();
$tester->testFn(42);
Output:
I'm new!My variable is set to 42Wow!
PHP
If I create a new instance of a parent class and a new instance of a child class, how can I change the variable in the parent class directly and view the change in the child class?
Take the following code:
class parentClass {
public $varA = 'dojo';
public function setVarA() {
$this->varA = 'something grand';
}
public function getVarA() {
return $this->varA;
}
}
class childClass extends parentClass {
public function useVarA() {
echo parent::getVarA();
}
}
$parentInstance = new parentClass();
$childInstance = new childClass();
$initialVarA = $parentInstance->getVarA(); // should set $initialVarA variable to 'dojo'
$childInstance->useVarA(); // should echo 'dojo'
$parentInstance->setVarA(); // should set $varA to 'something grand'
$changedVarA = $parentInstance->getVarA(); // should set $changedVarA variable to 'something grand'
$childInstance->useVarA(); // should echo 'something grand' but fails to do so...how can I do this?
If you have either a private or a protected variable (member) in the parent then you can access it simply like this from you child class:
$this->varA = ‘something’;
There reason why your child method does not reflect the change, is that child and parent are two different objects in separate memory space. If you want them to share a value you could make it static.
You don’t need to declare it public.
class Parent {
private $varA;
protected $varB;
public $varC;
protected static $varD;
public function getD() {
return self::$varD;
}
public function setD($value) {
self::$varD = $value;
}
}
class Child extends Parent {
public function getA() {
return $this->varA;
}
public function getB() {
return $this->varB;
}
public function getC() {
return $this->varC;
}
}
$child = new Child();
$child->getA(); // Will not work since $varA is private to Parent
$child->getB(); // Works fine because $varB is accessible by Parent and subclasses
$child->getC(); // Works fine but ...
$child->varC; // .. will also work.
$child->getD(); // Will work and reflect any changes to the parent or child.
If you don’t want all instance of the parent class to share values. You could pass on the parent or child to either new instance and through and update the values of all the related objects accordingly.
$parent->addChild(new Child());
And in the set method:
$this->varA = $value;
foreach ($this->children as $child) {
$child->setVarA($value);
}
Hopes this helps.