I tried to ask this question earlyer but I think I rushed the question and did not get accross what I was thinking...
Does the value and objects of $this get passed to an extened class?
<?php
class bar {
public function foo( $t ) {
$this->foo = $t;
}
}
class foo extends bar {
public function bar () {
return $this->foo;
}
}
$b = new bar();
$b->foo('bar');
$f = new foo();
echo $f->bar();
?>
if not, is there another decleration (instead of extends) that does without passing the object of the parent class to the child class?
regards,
Phil
Your example would yield an Undefined property: foo::$foo error. I think what you're trying to use is a static property:
class bar {
protected static $foo;
public function foo ($t) {
static::$foo = $t;
}
}
class foo extends bar {
public function bar () {
return static::$foo;
}
}
Then the following:
$b = new bar();
$b->foo('bar');
$f = new foo();
echo $f->bar();
... would echo bar, which looks like what is you're trying to achieve.
Related
class Foo {
protected static $a = 1;
protected $b = 2;
public function func() { return 'foo' . static::$a . $this->b; }
}
class Bar extends Foo {
protected static $a = 3;
protected $b = 4;
public function func() { return 'bar' . static::$a . $this->b; }
}
$obj = new Bar();
$obj->func(); // returns of course 'bar34'
Is there any option in PHP to call func() from Foo class?
In C++ I would cast $obj to Foo and simply call func()
Bar* obj = new Bar();
Foo* obj2 = (Bar*) obj;
obj2->func(); // returns 'foo14';
If you want to get down and dirty with Reflection then it's possible, but I'd strongly argue that this shouldn't be used anywhere near any production code. If you've got an instance of a child class, then you've got it for a reason, and if it's overridden a parent method then that has also happened for a reason.
Assuming you already know all this, then with that disclaimer out of the way, this should work in any remotely recent version of PHP:
class Foo { public function func() { echo 'I am the parent'; } }
class Bar extends Foo { public function func() { echo 'I am the child'; } }
// Create instance of child class
$bar = new Bar;
// Create reflection class
$reflected = new ReflectionClass(get_class($bar));
// Get parent method
$method = $reflected->getParentClass()->getMethod('func');
// Invoke method on child object
$method->invokeArgs($bar, []);
// I am the parent
See https://3v4l.org/NP6j8
This to me looks like a design issue more than anything else.
However if I were to handle this in a way that were easily readable and without rethinking my design I would do:
<?php
class Foo {
public function func() { return 'foo'; }
}
class Bar extends Foo {
public function func() { return 'bar'; }
public function parentFunc() { return parent::func(); }
}
$obj = new Bar();
$obj->parentFunc(); // returns of course 'foo'
Loek's answer also works, but doesn't call the method on the objects parent. It just calls the method on the classes parent. It all depends on the functionality you are looking for.
You could also do something like:
<?php
class Foo {
public function func() { return 'foo'; }
}
class Bar extends Foo {
public function func($parent = false) {
if ($parent) {
return parent::func();
}
return 'bar';
}
}
$obj = new Bar();
$obj->func(true); // returns of course 'foo'
Which is similar but without the need for the extra method.
Personally though I feel this issue likely requires a rethink in code design more than a coding solution.
-- edit --
To elaborate on 'a rethink in code design', I would ask myself "Why do I need an object that has two methods with the same name, but different functionalities? Is this not a job for two different objects? Trace the issue backwards until you find the design issue. Or the point at which the decision needs to be made as to which object your framework requires.
This isn't exactly what I'd call pretty, but it works and is relatively similar to what you described for C++; It works by calling get_parent_class() and then abusing PHP's ability to create objects from strings.
<?php
class Foo {
public function func() { echo 'foo'; }
}
class Bar extends Foo {
public function func() { echo 'bar'; }
}
$obj = new Bar();
$obj->func(); // Prints 'bar'
$parentClassString = get_parent_class($obj);
$newObj = new $parentClassString; // Gotta love PHP for magic like this
$newObj->func(); // Prints 'foo'
See this snippet to see it in action.
EDIT
It's a lot of work, but you could use so called Late Static Binding, perhaps more clearly explained in Jokerius's answer here. This requires you to write a crapload of custom code though, which I don't think is preferential. Overall the short answer seems to be: it isn't really possible.
I don't know should it help you but try to add this function in Bar class
public function callParent($function){
return parent::$function();
}
and call
echo $obj->callParent("func");
[UPDATED]
Also you can write cast function yourself
something like this
public function castAs($newClass) {
$obj = new $newClass;
foreach (get_object_vars($this) as $key => $name) {
$obj->$key = $name;
}
return $obj;
}
In PHP, is it possible to access the static properties of an object that is itself a property of another object, using similar syntax below:
<?php
class Foo
{
public $bar;
function __construct()
{
$this->bar = new Bar();
}
}
class Bar
{
const TEST = 123;
function __construct() {}
}
$bar = new Bar();
$foo = new Foo();
echo Bar::TEST; // ok
echo $bar::TEST; // ok
echo $foo->bar::TEST; // error
?>
Assign the property to a variable.
$foo = new Foo();
$bar = $foo->bar;
echo $bar::TEST; // that's good.
more tricky, but you can use ReflectionClass
echo (new ReflectionClass(get_class($foo->bar)))->getconstant("TEST");
You might have better luck using Late Static Binding instead of inheritance on that property. So it would be something like this (changed to an example from the above PHP manual page):
<?php
class A
{
public static function who()
{
echo __CLASS__;
}
public static function test()
{
static ::who();
// Here comes Late Static Bindings
}
}
class B extends A
{
public static function who()
{
echo __CLASS__;
}
}
B::test();
?>
Here's another thread that might be relevant or helpful: PHP Inheritance and Static Methods and Properties
How can I create something like
MyObject->property->method()
in PHP?
I only know how to create a method for a class:
class MyObject
{
public function MyMethod()
{
// do something
}
}
In Javascript I can easily do something like
var MyObject = {
property : {
method : function ()
{
// do something
}
}
}
How do I do that?
In Javascript you can create objects and methods inline, in PHP you need to have a class and instantiate it:
class Foo {
public function method() {}
}
class MyObject {
public $property;
public function __construct() {
$this->property = new Foo;
}
}
$o = new MyObject;
$o->property->method();
You can set an object as the value of a property. Something like this:
class Foo {
public $Bar;
public function __construct() {
$this->Bar = new Bar();
}
}
class Bar {
public function ShowBar() {
echo 'Bar';
}
}
$Foo = new Foo();
$Foor->Bar->ShowBar();
As others have correctly answered, this works differently in PHP and Javascript. And these differences are also the reason why in PHP you need to define the class methods before you run them. It might become a bit more dynamic in the future but I'm sure not on the level of Javascript.
You can however fake this a bit in PHP because you can assign functions to properties dynamically:
$myObject = new PropCall;
$myObject->property->method = function() {
echo "hello world\n";
};
$myObject->property->method();
This example outputs:
hello world
This does work because some little magic has been added in the instantiated object:
class PropCall
{
public function __call($name, $args) {
if (!isset($this->$name)) {
return null; // or error handle
}
return call_user_func_array($this->$name, $args);
}
public function __get($name) {
$this->$name = new PropCall;
return $this->$name;
}
}
This class code checks if a dynamic property has been added with the name of the method called - and then just calls the property as a function.
How can I access to class variable from outside without creating new instance in PHP ? Something like this:
class foo
{
public $bar;
}
echo foo::$bar;
Is it possible or I must create method that will print or return this value and use it or create new instance ( $a = new foo; echo $a->$bar ) ?
EDIT: I don't want to create constant but classic variable that will be changed later.
make this variable static to access it with out class object.
If you wanted to change static variable value by method then you need to use static method
you can try like this:
class foo
{
public static $bar ="google";
public static function changeVal($val){
self::$bar=$val;
}
}
foo::changeVal("changed :)");
echo foo::$bar;
Output : changed :)
Demo : https://eval.in/107138
You also can changed it like this without static method:
foo::$bar = "changed";
demo : https://eval.in/107139
like this:
class foo
{
public static $bar ="google";
}
echo foo::$bar;
Output: google
demo: https://eval.in/107126
IF it makes sense to use a static variable:
class foo{
public static $bar = 'example';
}
Which could be accessed like so:
echo foo::$bar;
If the value will never change during runtime, then you probably want a class constant (http://www.php.net/oop5.constants)
class foo {
const bar = 'abc';
}
...otherwise you want a public static variable (http://www.php.net/manual/en/language.oop5.static.php)
class foo {
public static $bar = 'abc';
}
...either way, access it like this
echo foo::bar;
You can access the class variable without creating instances only when the variable is markesd as static:
class foo
{
public static $bar;
}
This is how you use a class variable:
// with instantiation
class foo {
// initialize on declare
public $bar = 1;
// or initialize in __construct()
public function __construct(){
$this->bar = 1;
}
}
$foo = new foo();
var_dump($foo->bar);
// static way
class static_foo {
public static $bar = 1;
}
var_dump(static_foo::$bar);
And this is how you instantiate a class from a random class name string variable.
$foo = new foo();
$random_class_name = $foo->bar;
try {
// following line throws if class is not found
$rc = new \ReflectionClass($random_class_name);
$obj = $rc->newInstance();
// can be used with dynamic arguments
// $obj = $rc->newInstance(...);
// $obj = $rc->newInstanceArgs(array(...));
} catch(\Exception $Ex){
$obj = null;
}
if($obj){
// you have a dynamic object
}
What's your actual question?
What's the proper way to get new self() to use the current instance's constructor? In other words, when I do:
class Foo{
function create(){
return new self();
}
}
Class Bar extends Foo{
}
$b = new Bar();
echo get_class($b->create());
I want to see: Bar instead of: Foo
class Foo{
function create(){
$c = get_class($this);
return new $c();
}
}
Class Bar extends Foo{
}
$b = new Bar();
echo get_class($b->create());
Store the class type in a temp variable and then return a new instance of it.
public static function create()
{
$class = get_called_class();
return new $class();
}
This should work.
class Foo{
public static function create()
{
$class = get_called_class();
return new $class();
}
}
class Bar extends Foo{
}
$a = Foo::create();
$b = Bar::create();
echo get_class($a), PHP_EOL, get_class($b);
Shows:
Foo Bar
UPD:
If you want non-statics, then:
<?php
class Foo{
public function create()
{
$class = get_class($this);
return new $class();
}
}
class Bar extends Foo{}
$a = new Bar();
$b = $a->create();
echo get_class($a), PHP_EOL, get_class($b);
?>
Shows:
Bar Bar
Class Bar extends Foo {
function create(){
return self;
}}
If you call a function from a child class then it if it will search the nearest parent to call it. This is inheritance.
The idea is to use polymorphism in this situation. Redeclaring a function from child override it's parent's activity. If you want to run it's parent function too then you have to call it like parent::callee();