/    Sign up×
Community /Pin to ProfileBookmark

Reference calling class from parent?

So I have a parent class that creates instances of a variety of different child classes. Here’s a skeleton:

[code=php]abstract class ParentClass {
public static function create() {
return new <child class>() // instance of calling child class
}
}

class AChildClass extends ParentClass {

}

class AnotherChildClass extends ParentClass {

}

// sample calling code
AChildClass::create(); // should return an instance of AChildClass
AnotherChildClass::create() // should return an instance of AnotherChildClass[/code]

So what I need to do is create an instance of the class that called the create() function, but from what I can see, there is no easy way to do this. I have remedied it by setting a static $_class variable in each of the child classes containing the name of the class, then using

[code]new self::$_class()[/code]

in the create() method. This seems redundant though, and I figured there must be an easier way…

Anyone got anything?

to post a comment
PHP

5 Comments(s)

Copy linkTweet thisAlerts:
@MindzaiJul 09.2009 — If you are using a recent version of PHP5 you can use late static binding.

[code=php]public static function create() {
$calledClass = get_called_class();
return new $calledClass;
}[/code]


Otherwise you can probably hack something together with debug_backtrace().
Copy linkTweet thisAlerts:
@Four_StaplesauthorJul 10.2009 — If you are using a recent version of PHP5 you can use late static binding.

[code=php]public static function create() {
$calledClass = get_called_class();
return new $calledClass;
}[/code]


Otherwise you can probably hack something together with debug_backtrace().[/QUOTE]


Thanks, that's exactly what I was looking for.

I found a debug_backtrace version of get_called_class() but it doesn't work with call_user_func, which I need to use in my application. There's a bug with debug_backtrace that causes there to be no [i]file[/i] or [i]line[/i] data when a method is called via call_user_func.

I'll just stick with my messy solution until my host upgrades to 5.3.

Thanks again.
Copy linkTweet thisAlerts:
@NogDogJul 10.2009 — This all sort of begs the question, "Why?"

Without understanding why you see a need to have an inherited, static create() method, we may be addressing a symptom without dealing with the underlying cause. Perhaps the Factory Method Pattern or the Abstract Factory Pattern would address this underlying cause; then again, maybe not...there's no way to tell at this point.
Copy linkTweet thisAlerts:
@Four_StaplesauthorJul 10.2009 — Basically, I am writing an MVC-style framework + CMS. I'm writing a blogadmin controller right now, and I have a generic Model class that resembles the following:[code=php]abstract class Model extends Overloadable {
public function __construct($data) { }
public function save() { }
public function delete() { }
public static function get($id) { /* returns instance of calling class with data from database */ }
public static function getMultiple() { /* returns multiple instances in an array */ }
}[/code]

And I have three models (thus far) that extend this:[code=php]class BlogEntry extends Model {}
class BlogCategory extends Model {}
class BlogComment extends Model {}[/code]

This allows me to update/add/delete entries, comments, and categories all with 1 standard set of functions, while the child classes contain operations unique to their own data type. The problem comes when I want to use the static get() and getMultiple() functions to load instances from the database-- I do something like this:[code=php]$entries = BlogEntry::getMultiple()[/code]
But since the getMultiple method is in Model and has no idea which child class called it, it doesn't know what type of objects to return. I could make a getMultiple method in each child class and pass the class name through an argument to the parent method, but this would be repetition.
Copy linkTweet thisAlerts:
@NogDogJul 10.2009 — [i][Caveat: I am [b]not[/b] God's gift to the ojbect-oriented programming world.][/i]

I guess the root of what bothers me here is that it feels like the class is trying to do too much. I don't yet see a need for a static create() method instead of just instantiating via a normal constructor. The getMultiple() functionality, on the other hand, might best be handled via a separate class--perhaps following the Composite pattern?
×

Success!

Help @Four_Staples spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.28,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...