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();
Related
There is a property $modelName in class A that is accessed in this class using $this->modelName.
This property contains a name of another class B.
I want to call a static method of class B not creating an object of B.
Working code:
$b = $this->modelName;
$b::model()->findAll();
Question:
How to call model()->findAll() not using $b?
I tried $this->modelName::model()->findAll(); but it’s not working.
Do it:
class A{
public $modelName = 'B';
function callB(){
call_user_func(array($this->modelName, 'model'))->findAll();
}
}
class B{
private static $model = null;
static function model(){
if (!self::$model) {
self::$model = new B();
}
return self::$model;
}
function findAll(){
print __CLASS__.' method `findAll()`';
}
}
$A = new A;
$A->callB();
// B method `findAll()`
How can I return an instance of the class being called, when the method is in a parent class.
Eg. In the example below, how can I return an instance of B if I call B::foo();?
abstract class A
{
public static function foo()
{
$instance = new A(); // I want this to return a new instance of child class.
... Do things with instance ...
return $instance;
}
}
class B extends A
{
}
class C extends A
{
}
B::foo(); // Return an instance of B, not of the parent class.
C::foo(); // Return an instance of C, not of the parent class.
I know I can do it something like this, but is there a neater way:
abstract class A
{
abstract static function getInstance();
public static function foo()
{
$instance = $this->getInstance(); // I want this to return a new instance of child class.
... Do things with instance ...
return $instance;
}
}
class B extends A
{
public static function getInstance() {
return new B();
}
}
class C extends A
{
public static function getInstance() {
return new C();
}
}
$instance = new static;
You're looking for Late Static Binding.
http://www.php.net/manual/en/function.get-called-class.php
<?php
class foo {
static public function test() {
var_dump(get_called_class());
}
}
class bar extends foo {
}
foo::test();
bar::test();
?>
Result
string(3) "foo"
string(3) "bar"
So your function is going to be:
public static function foo()
{
$className = get_called_class();
$instance = new $className();
return $instance;
}
All you need is :
abstract class A {
public static function foo() {
$instance = new static();
return $instance ;
}
}
Or
abstract class A {
public static function foo() {
$name = get_called_class() ;
$instance = new $name;
return $instance ;
}
}
This's my second question, even thought, i answered the previous one, on my own. Anyway, I have a basic problem with OOP, on how to call a non-static method from another class. example:
We have a class named A in a file A.class.php
class A {
public function doSomething(){
//doing something.
}
}
and a second class named B on another file B.class.php
require_once 'A.class.php';
class B {
//Call the method doSomething() from the class A.
}
I think now it's clearn. How to : Call the method doSomething() from the class A ?
Class B will need an object of Class A to call the method on:
class B {
public function doStuff() {
$a = new A();
$a->doSomething();
}
}
Alternatively, you can create the instance of A outside of B and pass it into B's constructor to create a global reference to it (or pass it to an individual method, your choice):
class B {
private $a = null;
public function __construct($a) {
$this->a = $a;
}
public function doStuff() {
$this->a->doSomething();
}
}
$a = new A();
$b = new B($a);
How about injecting class A into B, making B dependant on A. This is the most primitive form of dependency injection:
class A
{
public function doSomething()
{
//doing something.
}
}
class B
{
private $a;
public function __construct( A $a )
{
$this->a = $a;
}
//Call the method doSomething() from the class A.
public function SomeFunction()
{
$this->a->doSomething();
}
}
This is constructed like this:
$a = new A();
$b = new B( $a );
You need to instantiate a an object of class A. You can only do this inside a method of class B.
class B{
public function doSomethingWithA(){
$a = new A();
return $a->doSomething();
}
}
class B {
public function __construct()
{
$a = new A;
$a->doSomething();
}
}
I know this is an old question but considering I found it today I figured I'd add something to #newfurniturey's answer.
If you wish to retain access to class B within class A this is what I did:
class A
{
private $b = null
public function __construct()
{
$this->b = new B($this);
if (!is_object($this->b) {
$this->throwError('No B');
}
$this->doSomething();
}
public function doSomething() {
$this->b->doStuff();
}
private function throwError($msg = false) {
if (!$msg) { die('Error'); }
die($msg);
}
}
class B {
public function doStuff() {
// do stuff
}
}
This is constructed like this:
$a = new A();
I would like to do something like:
library.php:
require_once "laucher.php";
class Test{
public function __construct(){
print "test";
}
}
class Foo extends Bar{
public function __construct(){
$t = new Test();
}
}
class Bar{
public function __construct(){
}
}
And in laucher.php, I would like to create a Foo object as $t = new Foo();
How Can I create Foo Objects in laucher.php? I would like to create an "auto-laucher" of Foo();
You have to include the file Foo is located in. So...
include("foo_file.php");
Then you can instantiate Foo.
$my_object = new Foo();
You cannot create Foo objects before Foo has been defined. Therefore you can't create Foo objects inside "laucher.php" if you include it before the class declarations.
However, if laucher.php is included after the class declarations you should be able to create Foo objects inside. So I think this would work:
class Test{
public function __construct(){
print "test";
}
}
class Foo extends Bar{
public function __construct(){
$t = new Test();
}
}
class Bar{
public function __construct(){
}
}
require_once "laucher.php";
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.