Create two same static classes in PHP - php

I am trying to extend static class in PHP. What I am running into is that once I change the variable in one of the extend classes, all others classes are changes as well. This is what I am trying to do:
class Fruit{
private static $name = Null;
public static function setName($name){
self::$name = $name;
}
public static function getName(){
return self::$name;
}
}
class Apple extends Fruit{};
class Banana extends Fruit{};
Apple::setName("apple");
Banana::setName("Banana");
echo Apple::getName();
echo Banana::getName();
I have read about late static binding and the keyword static::. But I cannot think of a way how to accomplish this without having to redeclare all Fruit's methods in both Apple and Banana.
I will be happy for any help
Thank You

This works:
<?php
class Fruit{
protected static $name = Null;
public static function setName($name){
static::$name = $name;
}
public static function getName(){
return static::$name;
}
}
class Apple extends Fruit{protected static $name;};
class Banana extends Fruit{protected static $name;};
Apple::setName("apple");
Banana::setName("Banana");
echo Apple::getName();
echo Banana::getName();
Unfortunately you need to re-declare the static properties you want to specialize, but your late static binding intuition was right :)

Although you should avoid such constructions, you could solve it quite nicely:
<?php
class Fruit {
protected static $names;
public static function setName($name)
{
self::$names[get_called_class()] = $name;
}
public static function getName()
{
return isset(self::$names[$key = get_called_class()]) ? self::$names[$key] : null;
}
}
So basically you store the data in just a single class, but specific to the class the method was called on. You don't need static as $name is always part of self, but 5.3 is still required because get_called_class is also part of late static binding.

Related

why used to interface rather than class in below condition.

i want to show a name.name may be in uppercase or in lowercase this will be depend on which class i will pass.i have to approach one is using class and second is interface which one is better and why ?
Solution using Class
class User{
}
class Iuser extends User{
private $name;
function __construct($name){
$this->name = $name;
}
function getName(){
return strtoupper($this->name);
}
}
class Wuser extends User{
private $name;
function __construct($name){
$this->name = $name;
}
function getName(){
return strtolower($this->name);
}
}
class Name{
public $u;
function __construct(User $u){
$this->u = $u;
}
function getName(){
$name = $this->u->getName();
return "Hi My Name is ".$name;
}
}
$name = "Deval Patel";
$iu = new Iuser($name);
$wu = new Wuser($name);
$user = new Name($wu);
echo $user->getName();
Solution Using Interface
interface User{
public function getName();
}
class Iuser implements User{
private $name;
function __construct($name){
$this->name = $name;
}
function getName(){
return strtoupper($this->name);
}
}
class Wuser implements User{
private $name;
function __construct($name){
$this->name = $name;
}
function getName(){
return strtolower($this->name);
}
}
class Name{
public $u;
function __construct(User $u){
$this->u = $u;
}
function getName(){
$name = $this->u->getName();
return "Hi My Name is ".$name;
}
}
$name = "Deval Patel";
$iu = new Iuser($name);
$wu = new Wuser($name);
$user = new Name($iu);
echo $user->getName();
Using the interface solution the getName() method is defined but not implemented in User interface (not shown in your code), so each class implementing it has to define the behaviour to get the name, whilst using abstract classes you may define the standard way to get the name, and override or overload the method in child classes when necessary.
So for your code, I think the best solution is the abstraction.
Remember to use interfaces when you want to force the developer to code the getName() method, and for abstract classes just to allow the developer to use the parent method getName(), or override/overload if necessary. Interfaces gives you more control and code reutilization.
Review the PHP object interfaces doc and PHP class abstraction doc, it may shed some light on your doubt.
I would use classes because you can reuse some code.
abstract class User
{
protected
$name;
public function __construct($name)
{
$this->name = $name;
}
abstract function getName();
}
class Iuser extends User
{
public function getName()
{
return strtoupper($this->name);
}
}
class Wuser extends User
{
function getName(){
return strtolower($this->name);
}
}
This way you can still use polymorphism and reuse some common code.
It's better then interface because the code reuse. You can still use an interface for the abstract class User but I think it would be an overkill.

PHP: is it possible to call a static class method from another static class?

Consider a static class (private constructor, only static methods & variables).
Now the rough class definition would look like this:
class A{
private function __construct(){}
public static test(){};
}
class B{
private function __construct(){}
}
Is it somehow possible to call something like B::A::test() ?
Or maybe through a variable? Something like B::$A::test() ?
I guess it is possible by some general call catching, but I can't figure it out...
IMPORTANT: Also, I want to call ANY other static class from B, not just from the A class...
EDIT2: What I want to achieve is to call static class through another static class, if possible... very similar to calling a method from object variable - but static class (obviously) is not ment to be instantiated.
EDIT3: Also possible solution is to call it as B::CLASSNAME_METHOD_NAME and catch it by __callStatic but I would rather do B::CLASSNAME::METHOD_NAME ...
Another possible solution:
If you don't want to create whole singleton, this could be solution - creating a partial singleton - some kind of singleton-hepler, altough using -> to call a static method could be confusing!
class AA{
private function __construct(){}
private static $instance;
public function getInstance(){ return empty(self::$instance)?(new self()):self::$instance; }
public function __call($method_name, $args) {
return AA::$method_name($args);
}
public static function test($a, $b){
echo "TEST: A:".$a." B:".$b;
}
}
class B{
private function __construct(){}
public static function A(){
return AA::getInstance();
}
}
B::A()->test("one", "two");
You would have to use this syntax:
class B {
const A = 'A';
}
$class = B::A;
$class::test()
This is essentially just the syntax for calling a static method on a variable class name. There's no nicer shortcut for it.
Note that I don't think such a pattern makes a lot of sense, your class design is too static at this point. You should be instantiating your classes and call $b->a->test(), which gives you more flexibility in your application design. Realistically B::A is hardcoded, it's not going to be anything other than 'A', so you may as well write A::test() directly.
If instead of a const you'd use a public static property which may vary at runtime, you now introduce global state into your app, which is also undesirable.
calling static function of a class from a static function of an another class
class A{
private function __construct(){}
public static function test()
{
echo 'from class A';
}
}
class B{
private function __construct(){}
public static function test()
{
return A::test();
}
}
A::test(); //outputs 'from class A'
B::test(); //outputs 'from class A'

Calling to a member function on a non-object Error

i'm having a trouble at the moment that i'm trying to access from a method of Wolf class to other method of Dog class. That's the code:
index.php
require_once 'Wolf.php';
require_once 'Dog.php';
class StackOverflowExample{
public static function run(){
$dog = new Dog("Cokey");
$wolf = new Wolf("Wolfenstein");
$wolf->hunt();
}
}
StackOverflowExample::run();
Wolf.php
class Wolf {
private $_name;
public function __construct($name){
$this->_name = $name;
}
public function hunt(){
return $dog->setLife(0);
}
}
Dog.php
class Dog {
private $_name;
private $_life= 100;
public function __construct($name){
$this->_name = $name;
}
public function setLife($life){
$this->_life = $life;
}
public function getLife(){
return $this->_life;
}
}
It gives me the next errors:
· Undefined variable: dog
· Call to a member function setLife() on a non-object
I have spent two days searching and I still having no way to fix.
Thanks you and sorry for my bad english.
What you should do is to pass $dog around, in the hunt method, like this:
public function hunt(Dog $dog){
return $dog->setLife(0);
}
You get the ability to validate that the dog variable is an instance of the expected class.
This method of passing objects around is called dependency injection.
If you want to pass around all sorts of animals you need to use another concept called inheritance:
abstract class Animal
{
public $_life;
public function setLife($life){
$this->_life = $life;
}
public function getLife(){
return $this->_life;
}
}
class Dog extends Animal
{
private $_name;
public function __construct($name){
$this->_name = $name;
}
}
class Wolf {
private $_name;
public function __construct($name){
$this->_name = $name;
}
public function hunt(Animal $animal){
return $animal->setLife(0);
}
}
Notice that the common methods and variables live in the parent class, and that you can create as many types as animals as you want.
If you follow this example you should find a way to declare the animal's name variable in the Animal class so you don't have to redefine it in all subclasses ;)
Replace
$dog->setLife(0);
by
Dog::setLife(0);

PHP Classes load() method good/bad practice?

Just wondering if you could shed some light on best practices?
Would having a load method in a Class be the correct/best way?
Class Test extends Foo{
public $id;
public $name;
public function __construct()
{
parent::__construct();
}
public function load($id, $name)
{
$this->id = $id;
$this->name = $name;
}
}
Or would it be concidered better practice to just have the load method logic in the constructor?
Class Test extends Foo{
public $id;
public $name;
public function __construct($id, $name)
{
parent::__construct();
$this->id = $id;
$this->name = $name;
}
}
The 2nd option seems to be more logical to me as it's one less method and it's called automatically etc, however, I've seen the 1st option more often. Is there a reason for this? Any help would be appreciated!
The second option is best. A constructor is meant to prepare the object for use. It is the perfect place to initialize properties etc. Unless you have a good reason for using load() instead of the constructor, go with the second example.
The first option uses slightly more abstraction, I suppose.
I can see a situation where you might need to copy the code and separating the variable assignments into a load() or init() function might make your code a litter easier to update for the new purpose.
An advantage of the 1st option is that you don't require the developer to supply the information straight away. Although it is more error prone since one might forget about calling the load function. If all other functions require $id and $name to be set it's best to require the arguments when creating a new object.
On the other hand not having the load function prevents you from reloading the object with new values later on in the code.
You can combine the two by calling the load function from the constructor:
Class Test extends Foo{
public $id;
public $name;
public function __construct( $id, $name )
{
parent::__construct();
$this->load( $id, $name );
}
public function load($id, $name)
{
$this->id = $id;
$this->name = $name;
}
}
OR if you don't require the values to be set on creation you can use PHPs funky function overloading stuff:
Class Test extends Foo{
public $id;
public $name;
public function __construct()
{
parent::__construct();
if( func_num_args() === 2 ){
call_user_func_array(array($this, 'load'), func_get_args() );
}
}
public function load($id, $name)
{
$this->id = $id;
$this->name = $name;
}
}
You could extend load() per particular member.
Making each property protected or private and providing a set/get function for one of them.
That's an acceptable way and sometimes is better than overloading your constructor with dependencies and logic.
Try this and see if it helps you:
Class Test extends Foo{
protected $id;
protected $name;
public function __construct()
{
parent::__construct();
}
public function setId($id) {
$this->id = $id;
}
public function setName($name) {
$this->name = $name;
}
public function getId() {
return $this->id;
}
public function getName() {
return $this->name;
}
}
It's called getters and setters and it's a more clean and robust approach.
Besides, as mentioned in other answers - It provides better re-usability, ability to have your object clean of data with null values, but that's all dependent on what is the intent of your class!

Why doesn't late static binding work with variables in PHP 5.3?

Let's start off with some code:
class Super {
protected static $color;
public static function setColor($color){
self::$color = $color;
}
public static function getColor() {
return self::$color;
}
}
class ChildA extends Super { }
class ChildB extends Super { }
ChildA::setColor('red');
ChildB::setColor('green');
echo ChildA::getColor();
echo ChildB::getColor();
Now, late static binding in PHP 5.3 using the static keyword works great with static methods, so I assumed it would do the same magic on static variables. Well, seems it doesn't. The example above does not print out "red" and then "green" as I first expected, but "green" and "green". Why doesn't this work on variables when it works on methods? Is there any other way to achieve the effect I expected?
Late static binding will only work for new definitions of variables / methods. Thus, in your example, the $color property of Super will always be modified instead of ChildA or ChildB. To make use of late static binding, you need to use the static keyword instead of self. Furthermore, you need to redefine the $color property of your ChildA and ChildB classes:
class Super {
protected static $color;
public static function setColor($color){
// static instead of self
static::$color = $color;
}
public static function getColor() {
// static instead of self
return static::$color;
}
}
class ChildA extends Super {
protected static $color;
}
class ChildB extends Super {
protected static $color;
}
ChildA::setColor('red');
ChildB::setColor('green');
echo Super::getColor(); // prints nothing (NULL = ''), expected
echo ChildA::getColor();// prints red
echo ChildB::getColor();// prints green

Categories