Here is my basic example:
class Foo {
public $toy = "car";
public function run() {
$this->toy = "train";
$bar = new Bar();
$bar->run();
}
}
class Bar extends Foo {
public function run() {
echo $this->toy;
}
}
$foo = new Foo();
$foo->run();
For some reason it will always echo car not train. What is the reason for this?
Foo run creates an object Bar, which has toy, initialized with car. So, the result is car, as expected.
Because you are creating a new Bar instance inside Foo::run. Changes you make to the Foo instance have no effect on the Bar instance. They are two different instances.
You can also see it this way: Whenever you instantiate an object from the child class, a new instance of the parent class will be created.
You can make the property static though, then it will be shared between all instances:
class Foo {
public static $toy = "car";
public function run() {
self::$toy = "train";
$bar = new Bar();
$bar->run();
}
}
class Bar extends Foo {
public function run() {
echo self::$toy;
}
}
What you do is "delegation": You create a new instance and call this instead of the parents method. What you are looking for is
parent::run();
This will call the parents method.
Related
I have class B. In this class I create object classB(). And I have a question how can I pass this new classB() to another class ?
class A
{
public classB $classB;
public function __construct()
{
$this->classB = new classB();
}
}
class C
{
public function example()
{
/// here I want to object new classB() created in class A
}
}
If I take your code, only slightly altered:
class A
{
public $b;
public function __construct()
{
$this->b = new B();
}
}
Then continue to create an object from that class:
$a = new A();
Then I can access the public property b, which is an object of class B, like so:
$accessB = $a->b;
Now if you want to use property b in another class you can do:
class C
{
public function example($anObject)
{
// here you can use $anObject
}
}
$c = new C();
$c->example($a->b);
That's all there is to it.
Please, next time you want to provide an example, make it meaningful. So instead of say "class A" call it, for instance, "class Car", and "class Wheel". Using meaningful class names, that clearly relate to each other, helps to understand what you're doing and helps to get away from abstract code.
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'
Let's say I have a huge class named Foo.
if I have to call this class several times in different classes, what is the best way to use it?
Note: Bar is not the only class that will use Foo.
Option #1 (create object when its needed):
class Bar
{
public function myMethod($arg)
{
$foo = new Foo();
$something = $foo->doSomething($arg);
return $something;
}
}
Option #2 (create it once):
class Bar
{
protected $foo;
public function __construct()
{
$this->foo = new Foo();
}
}
Option #3 (make Foo static):
class Bar
{
public function myMethod($arg)
{
return Foo::doSomething($arg);
}
}
Option #4:
// tell me the proper way to do it
The best way I'd say is to instantiate Foo outside the Bar class and inject it as a dependency - the best way to do this would be via constructor:
class Bar
{
private $foo;
public function __construct(Foo $foo)
{
$this->foo = foo;
}
}
$foo = new Foo();
$bar = new Bar($foo);
Then do the same for all classes that have Foo as a dependency. You can reuse the instance if it is suitable or you can create a new one if needed.
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();
}
}
I have a class which initiates another class, i'm not concerned with having a reference to the object i only need the method and have to pass in new parameters.
class A {
__set .....
}
class B extends A {
$anotherA = new A;
$anotherA->myName = 'stackoverflow';
}
in short i'd like to have class B extend A, init a new instance of A but i don't want to have to type "new" everytime, i've seen the following syntax:
B::A // something like that
but not sure if how to use it or if that would do what i'm trying to do?
What you could do is define a static method on the class that returns the new instance. It's basically a 'shortcut', but it does exactly the same in the background.
class C {
public static function instance()
{
return new C();
}
public function instanceMethod()
{
echo 'Hello World!';
}
}
Now you can call it like:
C::instance()->instanceMethod();
Here are some examples of static functions - they can be called without using 'new A' or 'new B'.
class A {
static function message($msg = 'I am Alpha') {
echo "hi there, $msg\n";
}
}
class B {
static function message() {
A::message("I am Beta");
}
}
A::message();
B::message();
I would create the instance of A in B's constructor, then you can instantiate B using either its constructor or static B::create(), which just acts as a shortcut. You could make the constructor private if you wanted all instantiation go through create().
class A {
// __set .....
}
class B extends A {
public function __construct() {
parent::__construct();
$anotherA = new A;
$anotherA->myName = 'stackoverflow';
}
public static function create() {
return new self();
}
}
new B();
B::create();
Since you are extending A in B, you could call the method of class A:
class B extends A {
public function someMethod() {
parent::someMethodName();
}
}
Alternatively, you could create a static method in the class:
class A {
public static function someStaticMethod() { ... }
}
A::someStaticMethod();
If you really want a new instance of A, you have to use the new operator. That's what it is for.