php oo programming parent to instantiate child [duplicate] - php

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What exactly is late-static binding in PHP?
I would like to build an abstract class that will instantiate it's child class using a static function.
<?php
class A
{
protected $value;
public function __construct($value)
{
$this->value = $value;
}
public static function create($value)
{
/* A must not know about B!
* I give that example for the context understanding */
return **new B**($value);
}
}
class B extends A
{
}
Of course A has not to know about B.. I do not know if it is possible and I do not want to have to implement the create function in all my 170 subclasses...
Do you think I should use a Factory that would return the instance of one of my 170 classes? That is cumbersome and not very maintainable..

I found out a solution, but is it ok?
<?php
class A
{
protected $value;
public function __construct($value)
{
$this->value = $value;
}
public static function create($value)
{
$child = get_called_class();
return new $child($value);
}
}
I tested it, it's working OK it's really useful in my context.. I do not know if it's ugly, because the parent class doesn't know about the child class, and if the Child class does not exists, the caller will not be allowed to call the create function..
Now, for my practical test, I use:
$graph->setBgcolor(Bgcolor::create('yellow')->valid());
with
public function setBgcolor(Bgcolor $bgcolor)

A successful implementation could be like this
class A
{
protected $value;
public static function create($value)
{
$type = "NotDivisible";
for ($i = 2; $i <= 10; $i++) {
if($value % $i == 0)
{
$type = "DivisibleBy".$i;
break;
}
}
$instance = new $type;
$instance->value = $value;
return $instance;
}
}
public class DivisibleBy2 extends A
{
}
public class DivisibleBy3 extends A
{
}
public class DivisibleBy5 extends A
{
}
...
so on.... (I haven't compiled it, sorry for syntax error)
Now as you know static method has nothing to do with the instance of object created because this is why we create a static method at the first place.
So you can put them in any other class and congrats you have implemented the factory design pattern.
However this is not a good implementation.

Another solution would NOT to use the static function and use basic new...
<?php
class A
{
protected $value;
public function __construct($value)
{
$this->value = $value;
}
}
Now, for my practical test, I use:
$graph->setBgcolor(new Bgcolor('yellow'));
with
public function setBgcolor(Bgcolor $bgcolor)
I still think that
Bgcolor::create('yellow')->foo()
looks better than
(new Bgcolor('yellow'))->foo()

Related

PHP inheritance of reflection methods [duplicate]

I have two classes: Action and MyAction. The latter is declared as:
class MyAction extends Action {/* some methods here */}
All I need is method in the Action class (only in it, because there will be a lot of inherited classes, and I don’t want to implement this method in all of them), which will return classname from a static call. Here is what I’m talking about:
Class Action {
function n(){/* something */}
}
And when I call it:
MyAction::n(); // it should return "MyAction"
But each declaration in the parent class has access only to the parent class __CLASS__ variable, which has the value “Action”.
Is there any possible way to do this?
__CLASS__ always returns the name of the class in which it was used, so it's not much help with a static method. If the method wasn't static you could simply use get_class($this). e.g.
class Action {
public function n(){
echo get_class($this);
}
}
class MyAction extends Action {
}
$foo=new MyAction;
$foo->n(); //displays 'MyAction'
Late static bindings, available in PHP 5.3+
Now that PHP 5.3 is released, you can use late static bindings, which let you resolve the target class for a static method call at runtime rather than when it is defined.
While the feature does not introduce a new magic constant to tell you the classname you were called through, it does provide a new function, get_called_class() which can tell you the name of the class a static method was called in. Here's an example:
Class Action {
public static function n() {
return get_called_class();
}
}
class MyAction extends Action {
}
echo MyAction::n(); //displays MyAction
Since 5.5 you can use class keyword for the class name resolution, which would be a lot faster than making function calls. Also works with interfaces.
// C extends B extends A
static::class // MyNamespace\ClassC when run in A
self::class // MyNamespace\ClassA when run in A
parent::class // MyNamespace\ClassB when run in C
MyClass::class // MyNamespace\MyClass
It's not the ideal solution, but it works on PHP < 5.3.0.
The code was copied from septuro.com
if(!function_exists('get_called_class')) {
class class_tools {
static $i = 0;
static $fl = null;
static function get_called_class() {
$bt = debug_backtrace();
if (self::$fl == $bt[2]['file'].$bt[2]['line']) {
self::$i++;
} else {
self::$i = 0;
self::$fl = $bt[2]['file'].$bt[2]['line'];
}
$lines = file($bt[2]['file']);
preg_match_all('/([a-zA-Z0-9\_]+)::'.$bt[2]['function'].'/',
$lines[$bt[2]['line']-1],
$matches);
return $matches[1][self::$i];
}
}
function get_called_class() {
return class_tools::get_called_class();
}
}
Now (when 5.3 has arrived) it's pretty simple:
http://php.net/manual/en/function.get-called-class.php
class MainSingleton {
private static $instances = array();
private static function get_called_class() {
$t = debug_backtrace();
return $t[count($t)-1]["class"];
}
public static function getInstance() {
$class = self::get_called_class();
if(!isset(self::$instances[$class]) ) {
self::$instances[$class] = new $class;
}
return self::$instances[$class];
}
}
class Singleton extends MainSingleton {
public static function getInstance()
{
return parent::getInstance();
}
protected function __construct() {
echo "A". PHP_EOL;
}
protected function __clone() {}
public function test() {
echo " * test called * ";
}
}
Singleton::getInstance()->test();
Singleton::getInstance()->test();
(PHP 5 >= 5.3.0, PHP 7)
get_called_class — The "Late Static Binding" class name
<?php
class Model
{
public static function find()
{
return get_called_class();
}
}
class User extends Model
{
}
echo User::find();
this link might be helpfull
There is no way, in the available PHP versions, to do what you want. Paul Dixon's solution is the only one. I mean, the code example, as the late static bindings feature he's talking about is available as of PHP 5.3, which is in beta.

Correct way of using polyporphism in php?

I'm new to object oriented php. And if there are no functions in the method testing() in the HumanClass, should i declare them as abstract?
<?php
class HumanClass
{
private $legs;
private $hands;
public function __construct($legs, $hands)
{
$this->legs = $legs;
$this->hands = $hands;
}
public function testing()
{
}
}
class StudentClass extends HumanClass
{
private $books;
public function __construct($legs, $hands, $books)
{
parent::__construct($legs, $hands);
$this->books = $books;
}
public function testing()
{
echo "StudentClass called.";
}
}
function callClass(HumanClass $c)
{
$c->testing();
}
$example = new StudentClass(4, 2, 1);
callClass($a);
?>
Is it possible to have something like this?
echo $a->testing();
instead of having another method to call testing().
Given the code that you give, it's far from clear what the testing() function is supposed to do other than just exist for you to try things. The answer to that will also determine whether the versions in the baseclass should remain there as empty function.
There are other options, too, e.g. that the derived class first invokes the baseclass (extending), or that the baseclass doesn't contain an abstract or concrete such function but only the derived one does. Which to choose is up to the informed programmer to decide.

PHP singletons and use of extended static properties

I've been running in circle for a couple hours with this problem.
Maybe it's not possible at all, or maybe there's a better OOP solution for this...
For example: I have two classes
class Base
{
public static $config;
}
class System extends Base
{
public function __construct()
{
self::$config = 2;
}
}
class Core extends Base
{
public function __construct()
{
self::$config = 3;
}
}
I always access those classes as singletons: System::HelloWorld(), Core::DoStuff();
I want the $Config attribute to be inherited from the Base class because I'm gonna need it in
almost every single class, so why define it every time over and over again.
The problem is, $Config attribute overrides itself as sonn as another class sets it's own value to it:
System::$config = 2;
Core::$config = 3;
print System::$config // it's 3 instead of 2
I do understand why that happens: Because the Base::$Config is Static - and that way - shared trough all the children. I do not want this, I want it to be static in each child, but not trough of it's children. It would be no problem, if I would actually instantiate the System and the Core classes, but I need them as Singletons...
Help me out here, maybe you know a better design pattern then this.
You don't need to use static variable at all,
<?php
Class Base{
public $Config;
}
Class System Extends Base{
Public static $obj = null;
Public static Function HelloWorld() {
if (!System::$obj) System::$obj = new System();
// call the object functions
// $obj->HelloWorld();
}
Public Function __Construct()
{
$this->Config = 2;
}
}
Class Core Extends Base{
Public Function __Construct()
{
$this->Config = 3;
}
}
?>
I came up with a relatively good solution for this. For those who may face the same problem, see here
<?php
// static change the attributes of the scope
class base
{
public static $config;
}
class a extends base
{
public function __construct()
{
self::$config = 1;
}
}
class b extends base
{
public function __construct()
{
self::$config = 2;
}
}
a::$config = 2;
b::$config = 3;
echo a::config, ',', b::$config; // 3,3
$a = new a();
echo base::$config, a::$config, b::$config, $a::$config; // 1 1 1 1

__get and __set magic methods not accessible

I have a class 'base' and a class 'loader', which looks like this.
class base {
protected $attributes = Array();
public $load = null;
function __construct() {
$this->load = loader::getInstance();
echo $this->load->welcome(); //prints Welcome foo
echo $this->load->name; //prints Foo
echo $this->name; //doesnt print anything and i want it to print Foo
}
public function __get($key) {
return array_key_exists($key, $this->attributes) ? $this->attributes[$key] : null;
}
public function __set($key, $value) {
$this->attributes[$key] = $value;
}
}
class loader {
private static $m_pInstance;
private function __construct() {
$this->name = "Foo";
}
public static function getInstance() {
if (!self::$m_pInstance) {
self::$m_pInstance = new loader();
}
return self::$m_pInstance;
}
function welcome() {
return "welcome Foo";
}
}
$b = new base();
Now what I want is a way to store variables from loader class and access them from base class using $this->variablename.
How can I achieve this? I don't want to use extends. Any idea ?
I don't feel like you've fully understood what coding the OOP way means. And usually Singletons are code smells so I'll just warn you:
There's probably a better way of accomplish you goal. If you provide more informations we will help you out. In its current form the answer is the following; just remember that I higly discourage its implementation in your code.
Assuming that you want to access only public (and non static) loader's variables as this->varname in the base class you should just insert this line in the beginning of the base class constructor:
$this->attributes = get_object_vars(loader::getInstance());
This will basically initialize the attributes array with all the loader public vars so that via your __get() method you can access its value.
On a side note, take a look at Dependency Injection design pattern in order to avoid using Singletons.
Your __get/__set methods access $this->attributes but not $this->load.
You could e.g. do something like (pseudocode)
function __get($key) {
- if $attribute has an element $key->$value return $attribute[$key] else
- if $load is an object having a property $key return $load->$key else
- return null;
}
see also: http://docs.php.net/property_exists
You can make static variable and then you can access this variable from anywhere
public statis $var = NULL;
and you can access it like this
classname::$var;

PHP: Detect instances of same class

I have a PHP Class which requires a unique value in its constructor. If multiple instances of the same class are passed the same value the results are horrific.
How would I go about detecting other instances of a Class so I can check and prevent this from happening before constructing any new ones?
A simple solution would be to keep a static array of the values inside the class. Then, when a new instance is created, check the static array's contents in the constructor.
Something like..
class Foo {
private static $usedValues = array();
public function __construct($val) {
if(in_array($val, self::$usedValues)) {
throw new Exception('blah');
}
self::$usedValues[] = $val;
}
}
I think the multiton pattern is right for you.
class Foo {
static protected $_instances = array();
static public function getInstance($id) {
if(!self::exists($id)) {
self::$_instances[$id] = new Foo($id);
}
return self::$_instances[$id];
}
static public function exists($id) {
return isset(self::$_instances[$id]);
}
protected function __construct($id) {
}
}

Categories