PHP create child class that is actual instance of parent class - php

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();
}
}

Related

Is it able to "extend" the existing function in PHP [duplicate]

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();
}
}

PHP: Include one class functions to another

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!

Is there a way to get a class name in php, convert it into a string and store it in a variable?

I have a class Bar with a method saveToTable($table), I need to have a default value for $table but that value needs to be dynamic, the dynamic value should be the name of the class Bar is extending to.
class Bar {
public function saveToTable($table) {
}
}
class Foo extends Bar {
}
$bar = new Foo;
$bar->saveToTable(); // in which case saveToTable() would have a param of 'foo' i.e. saveToTable('foo');
The solution I am using at the moment is explicitly specifying a $table property inside every class that extends Bar and assign it a string value of those classes' names, but this would defeat the purpose of making my app dynamic, plus it would be pretty cumbersome and prone to errors.
you can do it with late static binding which will reference to extended class
add this method to your Bar class
class Bar{
public function getClassName()
{
return static::class;
}
}
and now you can get the name
$bar = new Foo();
$bar->getClassName(); // returns Foo
Another solution, take care about namespaces, maybe you need delete
class Bar
{
public function saveToTable()
{
//Without namespace
$table = substr(static::class, strlen(__NAMESPACE__) + 1);
//With namespace
$table = static::class;
}
}
class Foo extends Bar
{
}
$bar = new Foo;
$bar->saveToTable();
Instead of using a parameter with default value for your method (wich can't be assigned dynamically)
consider using somethig like this:
class Bar {
protected $classname;
public function __construct() {
$this->classname = static::class;
}
public function saveToTable() {
echo $this->classname;
}
}
Now inside saveTotable() you have your class name as string.
class Foo extends Bar {
}
$bar = new Foo;
$bar->saveToTable(); // will echo 'Foo'

override a static variable

I have two classes (Model and User) but I have a problem so I have tried to explain it in a simple example :
class person
{
protected static $todo ="nothing";
public function __construct(){}
public function get_what_todo()
{
echo self::$todo;
}
}
class student extends person
{
protected static $todo ="studing";
}
$s = new student();
$s->get_what_todo(); // this will show the word (nothing)
//but I want to show the word (studing)
Please give me a solution but without writing any function in the student class I only want to make declarations there :) and thank you :)
The principle is called "late static binding", and was introduced in PHP 5.3.0; with the self keyword to access the property defined in the calling class within the inheritance tree, or static to access the property defined in the child class within that inheritance tree.
class person
{
protected static $todo ="nothing";
public function __construct(){}
public function get_what_todo()
{
echo static::$todo; // change self:: to static::
}
}
class student extends person
{
protected static $todo ="studying";
}
class teacher extends person
{
protected static $todo ="marking";
}
class guest extends person
{
}
$s = new student();
$s->get_what_todo(); // this will show the "studying" from the instantiated child class
$t = new teacher();
$t->get_what_todo(); // this will show the "marking" from the instantiated child class
$g = new guest();
$g->get_what_todo(); // this will show the "nothing" from the parent class,
// because $todo is not overriden in the child class
The reliable way to override a static variable is to do it by redeclaring it. Some people may suggest modifying it in the construct method, but I don't think that's reliable.
It won't reflect the changes until the class is constructed at least once. And of course, in class methods, don't forget to call the static variable using "static::" instead of "self::" when you want to always access the overridden variable.
Here's an example of what I mean:
The class Foo is the base class, the class Bar is changing the variable inside its constructor, and the class Baz is overriding the variable in its declaration.
class Foo
{
public static $a = "base";
}
class Bar extends Foo
{
function __construct()
{
self::$a = "overridden";
}
}
class Baz extends Foo
{
public static $a = "overridden";
}
echo 'Foo: ' . Foo::$a . '<br>';
echo 'Bar: ' . Bar::$a . '<br>';
echo 'Baz: ' . Baz::$a . '<br>';
new Bar();
echo 'Bar after instantiation: ' . Bar::$a;
This is the output from phptester.net
Foo: base
Bar: base
Baz: overridden
Bar after instantiation: overridden
As you can see, Bar's way of changing the variable isn't taking effect until after the constructor is called at least once.
EDIT: However, there is another way to edit a variable permanently and reliably: do it after the class declaration. This is especially handy if you only need to modify a variable and not completely override it, like for example an array. It feels a bit dirty, but in theory should work everytime.
class Foo
{
public static $a = [
'a' => 'a'
];
}
class Bar extends Foo
{
public static $a;
}
Bar::$a = Foo::$a;
Bar::$a['b'] = 'b';
echo 'Foo: ' . print_r(Foo::$a, true) . '<br>';
echo 'Bar: ' . print_r(Bar::$a, true) . '<br>';
This is the output from phptester.net
Foo: Array ( [a] => a )
Bar: Array ( [a] => a [b] => b )
EDIT 2: This last method also gets picked up by ReflectionClass::getStaticPropertyValue in my tests.
you can try set variable in construction
class person
{
protected static $todo = null;
public function __construct(){
self::$todo = "nothing";
}
public function get_what_todo()
{
echo self::$todo;
}
}
class student extends person
{
public function __construct() {
self::$todo = "student";
}
}
$s = new student();
$s->get_what_todo();
you can try set parent variable in construction
class person
{
protected static $todo = null;
public function __construct(){
self::$todo = "nothing";
}
public function get_what_todo()
{
echo self::$todo;
}
}
class student extends person
{
public function __construct() {
parent::$todo = "student";
}
}
$s = new student();
$s->get_what_todo();

Calling an overridden parent method

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();
}
}

Categories