In the sample code below, the method test() in parent class Foo is overridden by the method test() in child class Bar. Is it possible to call Foo::test() from Bar::test()?
class Foo
{
$text = "world\n";
protected function test() {
echo $this->text;
}
}// class Foo
class Bar extends Foo
{
public function test() {
echo "Hello, ";
// Cannot use 'parent::test()' because, in this case,
// Foo::test() requires object data from $this
parent::test();
}
}// class Bar extends Foo
$x = new Bar;
$x->test();
Use parent:: before method name, e.g.
parent::test();
See parent
parent::test();
(see Example #3 at http://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php)
Just set visibility levels at $text property.
private $text = "world\n";
Calling a parent method may be considered bad practice or code smell and may indicate programming logic that can be improved in a way, that the child doesn't have to call the parent. A good generic description is provided by Wikipedia.
An implementation without calling parent would look like:
abstract class Foo
{
$text = "world\n";
public function test() {
$this->test_child();
echo $this->text;
}
abstract protected function test_child();
}// class Foo
class Bar extends Foo
{
protected function test_child() {
echo "Hello, ";
}
}// class Bar extends Foo
$x = new Bar;
$x->test();
Judging by your comments on the pastebin, I'd say you can't.
Maybe if you had something like this?
class foo {
public function foo($instance = null) {
if ($instance) {
// Set state, etc.
}
else {
// Regular object creation
}
}
class foo2 extends foo {
public function test() {
echo "Hello, ";
// New foo instance, using current (foo2) instance in constructor
$x = new foo($this);
// Call test() method from foo
$x->test();
}
}
Related
I have large class foo, that I want to split to two separate classes (and files);
My class foo uses contruct function and noumerous $this references.
I need a second class bar to be an extension for original foo class, so I could still use contruction with additional parameter if to include bar class;
$includeBar = true;
$foo = new foo($config, $includeBar);
I've tried putting it this way:
Class bar extends foo {
public function barFunction(){
//some function of bar
}
}
Class foo {
public function __construct($config, $includeBar = true) {
if ($includeBar) {
include_once 'bar.php';
}
}
}
But when I call:
$foo = new foo($config, true);
$foo->barFunction();
It fails, saying
PHP Fatal error: Uncaught Error: Call to undefined method foo::barFunction()
What am I doing wrong? pls help, got stuck
It should be the other way round.
Bar is your base class, that contains all the methods that every sub class also needs. Foo is the extention, the extras, so Foo extends Bar.
<?php
// file bar.php
Class Bar {
public function __construct($config) {
$this->config = $config;
}
public function barFunction() {
echo "I'm everybody ".$this->config['msg'];
}
}
// file foo.php
require_once('bar.php');
Class Foo extends Bar {
public function fooOnly() {
echo "I'm foo ".$this->config['msg'];
}
}
// consuming file index.php
include('foo.php');
$config = array('msg'=>'and I need coffee');
$foo = new foo($config);
$foo->barFunction(); // we can call this, because foo extends bar
// this won't work:
$bar = new Bar($config);
$bar->fooOnly();
// but this:
$bar->barFunction();
$foo->fooOnly();
(all the includes/requires can be omitted when using a proper autoloader!)
If you want reuse class methods or separate class method implementation I think you can use trait and then you can use keyword use to require functions to your class.
For example:
<?php
class Base {
public function sayHello() {
echo 'Hello ';
}
}
trait SayWorld {
public function sayHello() {
parent::sayHello();
echo 'World!';
}
}
class MyHelloWorld extends Base {
use SayWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
?>
The above example will output:
Hello World!
OK - What I'm trying to do is kind of convoluted and I'm not sure if its even possible or if there is another "proper" way to do this but here it is in a nutshell:
class foo {
var $testvar = "foo";
function doTest() {
echo $this->testvar . "\n";
$t = new bar;
$t->updateParent();
echo $this->testvar;
}
}
class bar extends foo {
function updateParent() {
$this->testvar = "bar";
}
}
/*
What I get:
foo
foo
What I want:
foo
bar
*/
The reason I'm doing this is I'm designing a template engine and basically for my purposes the foo class is the main class that has the bulk of my application code. The system is designed so the users can create their own template php files which are loaded by the application within the context of a foo method. I want to set all the properties and methods of foo to private save for certain ones that will be protected and thus accessible to bar. The point being I want the users template php code to have access to only a limited number of functions of the parent class when I include their code.
A better example would be:
class foo {
protected $db;
private $settings;
function SomeAction() {
// some code that results in a template needing to be loaded
// code that determines the template file
$template = new bar;
$template->loadTemplate($file);
}
}
class bar extends foo {
function loadTemplate($file) {
//if file exists
require($file);
// has access $db driver class (without creating a new instance of it)
// does not have access to the $settings property
}
}
Any Ideas?
It seems strange to me that you are extending the foo class just to give access of $db may be some more properties. but this doesn't make sense to me. You should pass the dependency to both classes.
class foo {
protected $db;
private $settings;
function SomeAction(bar $bar) {
// some code that results in a template needing to be loaded
// code that determines the template file
$bar->loadTemplate($file);
}
}
class bar {
function loadTemplate($file, Gateway $db) {
// use $db here
//if file exists
require($file);
}
}
I believe you're looking for parent
Give this a try:
class foo {
var $testvar = "foo";
function doTest() {
echo $this->testvar . "\n";
$t = new bar;
$t->updateParent();
echo $this->testvar;
}
}
class bar extends foo {
function updateParent() {
parent::testvar = "bar";
}
}
/*
What I get:
foo
foo
What I want:
foo
bar
*/
try this
<?php
class foo {
var $testvar = "foo";
function doTest() {
echo $this->testvar . "\n";
$R =$this->updateParent();
echo $R;
}
}
class bar extends foo {
function __construct()
{
parent:: doTest();
}
function updateParent() {
$testvar = "bar";
return $testvar;
}
}
$t = new bar;
Instead of using the literal name of the base class in your code, you should be using the special name parent, which refers to the name of your base class as given in the extends declaration of your class
Every object instance is also an instance of it's parent.
You make all properties private in the parent and offer secured access through public methods. All public methods will be available to child classes as if they were their own, without access to private properties.
class foo {
private $db;
public function dbSelect() {
return $this->db->select();// Example
}
}
class bar extends foo {
public function loadTemplate($file) {
require($file);
$selected = $this->dbSelect();
}
}
Is something like the following possible in PHP?
$blah = 'foo1';
class foo2 extends $blah {
//...
}
class foo1 {
//...
}
This gives an error.
I want to dynamically set $blah so I can extend whatever class I want.
Edit: The reason for wanting to do this because I wanted to use a function out of another class in a related class. In the end it would have been something like:
Final extends foo1 extends foo2 extends foo3 extends foo4 extends parent { ... }
In the end I decided to instantiate the other class within the class and use it. Not the best options because they both you 2 of the same classes, but this won't be used that often, so it will work for now.
You're assuming here php executes top to bottom, but it doesn't quite work like that:
<?php
foo(); # works
function foo(){
print "bar";
}
<?php
foo(); #dies
if( $i == 1 )
{
function foo(){
print "bar";
}
}
<?php
$i = 1;
if( $i == 1 )
{
function foo(){
print "bar";
}
}
foo(); #works
Now, although you can conditionally create classes:
<?php
class A { }
class B { }
if( false ){
class C extends B {
public static function bar(){
print "baz";
}
}
}
C::bar(); # dies
You cant instantiate one at runtime from a variable:
<?php
class A { }
class B { }
$x = 'B';
if( false ){
class C extends $x {
public static function bar(){
print "baz";
}
}
}
C::bar();
---> Parse error: syntax error, unexpected T_VARIABLE, expecting T_STRING in /tmp/eg.php on line 7
There is a way to do it with Eval, but you really don't want to go there:
<?php
class A { }
class B { }
$x = 'B';
if( true ){
$code =<<<EOF
class C extends $x {
public static function bar(){
print "baz";
}
}
EOF;
eval( $code );
}
C::bar();
$o = new C;
if ( $o instanceof $x )
{
print "WIN!\n";
}
--->barWIN!
However, there is a more important question here:
Why the hell would you want to extend a different class at runtime
Anybody using your code will want to hold you down and whip you for that.
( Alternatively, if you're into whipping, do that eval trick )
I know this question was asked a long time ago, but the answer is relatively simple.
Assuming you want to extend class foo if class foo exists, or class bar if it doesn't, you'd use:
if(!class_exists('foo')) {
class foo extends bar {
function __construct() {
parent::__construct();
}
}
}
class myclass extends foo{
//YOUR CLASS HERE
}
Using PHP overloading you can accomplish this to a certain extent.
class variable_class {
public $orginalBaseClass;
public $orginalArgs;
public function __construct() {
// Get constructor parameters.
$this->orginalArgs = func_get_args();
// Get class name from args or 3rd party source.
$classname = 'stdClass';
// Pass along args to new class.
$this->orginalBaseClass = new $classname($this->orginalArgs);
}
public function __call($name, $arguments) {
// Pass all method calls to the orginalBaseClass.
return call_user_func_array(array($this->orginalBaseClass, $name), $arguments);
}
}
I'm using this pattern inside a Drupal module for prefetching data from the cache.
I don't see how this would be particularly useful, but to answer your question... no. There's no way to dynamically do that because the generated class has to be instantiated before the variable is evaluated (if that makes sense).
To put it simply: The class must exist before the code can be properly executed.
If you don't have too many values for $blah, you could extend each one in a different file then require_once "classes/foo_$blah.php"
Otherwise, you're stuck with the eval() solution... good luck with that... :)
I assume that this is for ease-of-maintenance, right? Extending a class at run time really is pretty crazy.
class SuperClassOne { /* code */ }
class SuperClassTwo { /* code */ }
class IntermediateClass extends SuperClassOne { /* empty! */ }
class DescendantClassFoo extends IntermediateClass{ }
class DescendantClassBar extends IntermediateClass{ }
class DescendantClassBaz extends IntermediateClass{ }
Then, when you want to change all your DescendantClass* classes, you just have to change what the IntermediateClass extends:
class IntermediateClass extends SuperClassTwo { }
I tested something with defines and barking:
<?php
define("INHERIT",A);
class A{
public function bark(){
return "I'm A";
}
}
class B{
public function bark(){
return "I'm B";
}
}
class C extends INHERIT{}
//main?
$dog = new C();
echo $dog->bark();
?>
the output is:
Fatal error: Class 'INHERIT' not found
in D:\sites\inherit.php on line 15
so the answer for "are variable class extensions possible?" is: No.
you should have tried $$
$blah = 'foo1';
class foo2 extends $$blah {
//...
}
class foo1 {
//...
}
In the sample code below, the method test() in parent class Foo is overridden by the method test() in child class Bar. Is it possible to call Foo::test() from Bar::test()?
class Foo
{
$text = "world\n";
protected function test() {
echo $this->text;
}
}// class Foo
class Bar extends Foo
{
public function test() {
echo "Hello, ";
// Cannot use 'parent::test()' because, in this case,
// Foo::test() requires object data from $this
parent::test();
}
}// class Bar extends Foo
$x = new Bar;
$x->test();
Use parent:: before method name, e.g.
parent::test();
See parent
parent::test();
(see Example #3 at http://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php)
Just set visibility levels at $text property.
private $text = "world\n";
Calling a parent method may be considered bad practice or code smell and may indicate programming logic that can be improved in a way, that the child doesn't have to call the parent. A good generic description is provided by Wikipedia.
An implementation without calling parent would look like:
abstract class Foo
{
$text = "world\n";
public function test() {
$this->test_child();
echo $this->text;
}
abstract protected function test_child();
}// class Foo
class Bar extends Foo
{
protected function test_child() {
echo "Hello, ";
}
}// class Bar extends Foo
$x = new Bar;
$x->test();
Judging by your comments on the pastebin, I'd say you can't.
Maybe if you had something like this?
class foo {
public function foo($instance = null) {
if ($instance) {
// Set state, etc.
}
else {
// Regular object creation
}
}
class foo2 extends foo {
public function test() {
echo "Hello, ";
// New foo instance, using current (foo2) instance in constructor
$x = new foo($this);
// Call test() method from foo
$x->test();
}
}
Is something like the following possible in PHP?
$blah = 'foo1';
class foo2 extends $blah {
//...
}
class foo1 {
//...
}
This gives an error.
I want to dynamically set $blah so I can extend whatever class I want.
Edit: The reason for wanting to do this because I wanted to use a function out of another class in a related class. In the end it would have been something like:
Final extends foo1 extends foo2 extends foo3 extends foo4 extends parent { ... }
In the end I decided to instantiate the other class within the class and use it. Not the best options because they both you 2 of the same classes, but this won't be used that often, so it will work for now.
You're assuming here php executes top to bottom, but it doesn't quite work like that:
<?php
foo(); # works
function foo(){
print "bar";
}
<?php
foo(); #dies
if( $i == 1 )
{
function foo(){
print "bar";
}
}
<?php
$i = 1;
if( $i == 1 )
{
function foo(){
print "bar";
}
}
foo(); #works
Now, although you can conditionally create classes:
<?php
class A { }
class B { }
if( false ){
class C extends B {
public static function bar(){
print "baz";
}
}
}
C::bar(); # dies
You cant instantiate one at runtime from a variable:
<?php
class A { }
class B { }
$x = 'B';
if( false ){
class C extends $x {
public static function bar(){
print "baz";
}
}
}
C::bar();
---> Parse error: syntax error, unexpected T_VARIABLE, expecting T_STRING in /tmp/eg.php on line 7
There is a way to do it with Eval, but you really don't want to go there:
<?php
class A { }
class B { }
$x = 'B';
if( true ){
$code =<<<EOF
class C extends $x {
public static function bar(){
print "baz";
}
}
EOF;
eval( $code );
}
C::bar();
$o = new C;
if ( $o instanceof $x )
{
print "WIN!\n";
}
--->barWIN!
However, there is a more important question here:
Why the hell would you want to extend a different class at runtime
Anybody using your code will want to hold you down and whip you for that.
( Alternatively, if you're into whipping, do that eval trick )
I know this question was asked a long time ago, but the answer is relatively simple.
Assuming you want to extend class foo if class foo exists, or class bar if it doesn't, you'd use:
if(!class_exists('foo')) {
class foo extends bar {
function __construct() {
parent::__construct();
}
}
}
class myclass extends foo{
//YOUR CLASS HERE
}
Using PHP overloading you can accomplish this to a certain extent.
class variable_class {
public $orginalBaseClass;
public $orginalArgs;
public function __construct() {
// Get constructor parameters.
$this->orginalArgs = func_get_args();
// Get class name from args or 3rd party source.
$classname = 'stdClass';
// Pass along args to new class.
$this->orginalBaseClass = new $classname($this->orginalArgs);
}
public function __call($name, $arguments) {
// Pass all method calls to the orginalBaseClass.
return call_user_func_array(array($this->orginalBaseClass, $name), $arguments);
}
}
I'm using this pattern inside a Drupal module for prefetching data from the cache.
I don't see how this would be particularly useful, but to answer your question... no. There's no way to dynamically do that because the generated class has to be instantiated before the variable is evaluated (if that makes sense).
To put it simply: The class must exist before the code can be properly executed.
If you don't have too many values for $blah, you could extend each one in a different file then require_once "classes/foo_$blah.php"
Otherwise, you're stuck with the eval() solution... good luck with that... :)
I assume that this is for ease-of-maintenance, right? Extending a class at run time really is pretty crazy.
class SuperClassOne { /* code */ }
class SuperClassTwo { /* code */ }
class IntermediateClass extends SuperClassOne { /* empty! */ }
class DescendantClassFoo extends IntermediateClass{ }
class DescendantClassBar extends IntermediateClass{ }
class DescendantClassBaz extends IntermediateClass{ }
Then, when you want to change all your DescendantClass* classes, you just have to change what the IntermediateClass extends:
class IntermediateClass extends SuperClassTwo { }
I tested something with defines and barking:
<?php
define("INHERIT",A);
class A{
public function bark(){
return "I'm A";
}
}
class B{
public function bark(){
return "I'm B";
}
}
class C extends INHERIT{}
//main?
$dog = new C();
echo $dog->bark();
?>
the output is:
Fatal error: Class 'INHERIT' not found
in D:\sites\inherit.php on line 15
so the answer for "are variable class extensions possible?" is: No.
you should have tried $$
$blah = 'foo1';
class foo2 extends $$blah {
//...
}
class foo1 {
//...
}