Declaring a new static variable outside of Class - php

Is there a way declaring new static variables outside of that class even if it's not set in class?
// Using this class as a static object.
Class someclass {
// There is no definition for static variables.
}
// This can be initialized
Class classA {
public function __construct() {
// Some codes goes here
}
}
/* Declaration */
// Notice that there is no static declaration for $classA in someclass
$class = 'classA'
someclass::$$class = new $class();
How can it be done?
Thank you for your advices.

This can't be done, because static variables, well... are STATIC and therefore cannot be declared dynamically.
EDIT:
You might want to try using a registry.
class Registry {
/**
*
* Array of instances
* #var array
*/
private static $instances = array();
/**
*
* Returns an instance of a given class.
* #param string $class_name
*/
public static function getInstance($class_name) {
if(!isset(self::$instances[$class_name])) {
self::$instances[$class_name] = new $class_name;
}
return self::$instances[$class_name];
}
}
Registry::getInstance('YourClass');

__get() magic method in PHP is called when you access non-existent property of an object.
http://php.net/manual/en/language.oop5.magic.php
You may have a container within which you'll handle this.
Edit:
See this:
Magic __get getter for static properties in PHP

Related

Type Hinting abstract class singleton

How would one Type Hint a static singleton-returning method on an abstract class, which returns instances of the extending called classes?
For example, let's look at the following code:
<?php
abstract class Foo {
/** #return Foo */
public function init() {
static $instance;
if ( is_null($instance) ) {
$class = get_called_class();
$instance = new $class();
}
return $instance;
}
}
class Bar extends Foo {
public $name = "Bar name";
}
class Baz extends Foo {
public $age = 42;
}
My intention is for tools such as PhpStorm to understand that Bar::init() returns an object of type Bar and that Baz::init() returns an object of type Baz. Thus, for example, objects created from the Baz::init() method would auto-complete the name property but not the age property.
Obviously the current type hint #return Foo is wrong as the method will never return an object instance of an abstract class.
So #return static will work in this case for PHPStorm. It is the easiest option and will provide what you are looking for.
Optionally you can use the #method annotation against the class although this is very manual and needs to be done for each class. There is another strange thing with this method in PHPStorm where if you navigate to the init() method (ctrl+click or w/e) it will navigate to this annotation first. However this is how that looks:
/**
* #method Bar init()
*/
class Baz extends Foo
{
}
Where optionally as a final resort--and I really don't think you will need it but its here for completeness. Extend the method and add your return annotation as you would a normal method.
/**
* #return Baz
*/
public function init()
{
return parent::init();
}
You could try this:
abstract class Foo {
/** #return static */
public function init() {
static $instance;
if ( is_null($instance) ) {
$class = get_called_class();
$instance = new $class();
}
return $instance;
}
}
This will probably require PhpStorm to be set up with PHP 5.3+ type hints to work.

PHP | Access to undeclared static property

After trying several attempts at this for some reason i get the error Access to undeclared static property when i try to make an object out my class.
My class:
final class repo {
var $b;
/**
* #var \Guzzle\Http\Client
*/
protected $client;
function repo($myvar)
{
static::$b = $myvar;
$this->client = $b;
}
}
Me making an object:
$myobj = new repo("test");
You should declare $b as static variable.
Also note that method as a class name is deprecated now see the details here
final class repo {
public static $b;
/**
* #var \Guzzle\Http\Client
*/
protected $client;
function repo($myvar)
{
static::$b = $myvar;
$this->client = static::$b;
}
}
The declaration var $b; is PHP 4. PHP 5 allows it and it is equivalent to public $b;.
However, it is deprecated and if you use a proper error reporting (error_reporting(E_ALL); during development) you get a warning about it. You should use the PHP 5 visibility kewords instead.
Also, the declaration function repo($myvar) is a PHP 4 constructor style, also accepted but deprecated. You should use the PHP 5 __constructor() syntax.
You access $b as static::$b and this is not compatible with its declaration (equivalent, as I said above, with public $b). If you want it to be a class property (this is what static does) you have to declare it as a class property (i.e. public static $b).
Putting everything together, the proper way to write your class is:
final class repo {
// public static members are global variables; avoid making them public
/** #var \Guzzle\Http\Client */
private static $b;
// since the class is final, "protected" is the same as "private"
/** #var \Guzzle\Http\Client */
protected $client;
// PHP 5 constructor. public to allow the class to be instantiated.
// $myvar is probably a \Guzzle\Http\Client object
public __construct(\Guzzle\Http\Client $myvar)
{
static::$b = $myvar;
// $this->b probably works but static::$b is more clear
// because $b is a class property not an instance property
$this->client = static::$b;
}
}
Try this
final class repo {
public $b;
/**
* #var \Guzzle\Http\Client
*/
protected $client;
function repo($myvar)
{
$this->b = $myvar;
$this->client = $this->b;
}
}
Note: static::/self:: is used on static functions.

Define type for PHPUnit's mock objects

I was wondering if its possible to use phpdoc to define some object in specific scope (inside a method only) as PHPUni's Mock, so in that method i can take advantage of type-hints, such as ->expected, ->methods and so on, just like when you just create the mock without addressing it to its real class.
here is an demonstration:
class someTest extends PHPUnit
{
// here, usually we define the real class (SomeClass in this example)
/** #var SomeClass */
private $someMock;
public function setUp()
{
$this->someMock = $this->getMock(SomeClass::class);
}
public function testSomethingInSomeClass()
{
// here i expect the type hint i defined in the beginning of this test class and its fine
$a = $this->someMock->someMethodFromSomeClass();
}
private function setSomeMethodOnMock()
{
// but here i would like to have the type-hint for phpunit's mock object
// e.g. ->expects, ->method() , ->willReturn() , etc.
// if i don't define the mock alias the class type i get will be something like Mock_SomeClass_9873432
$this->someMock->....
}
}
/**
* #var SomeClass|\PHPUnit_Framework_MockObject_MockObject
*/
private $someMock;
You can do the same thing with methods:
/**
* #return SomeClass|\PHPUnit_Framework_MockObject_MockObject
*/
private function getSomeMock()
{
//....
}

Object slicing in PHP

Is it possible to get the base object from derived object in php
Something like this
class base {}
class derived extends base{
public function getBase()
{
return (base)$this;
}
The above code, throws out a error
You can use parent:: to resolve to a parent method, property or constant.
If you're trying to get the name of the base class, here's a way to do that:
class base {
public function getClassName() {
return "base";
}
}
class derived extends base{
public function getBaseClassName() {
return parent::getClassName();
}
public function getClassName() {
return "derived";
}
}
$d = new derived();
echo $d->getBaseClassName();
Edit: When you use inheritance to extend a class (eg: derived extends base), you are saying that derived is a kind of base, and all instances of derived are also instances of base. In most OO languages, the two instances, base and derived are not separate entities, and they can not be treated separately. (C++ is an exception to the rule in this regard).
If you need to treat the instances separately, then inheritance is the wrong tool for the job. Use extension by containment, rather than inheritance. This will look something like the following:
class base {
public someBaseFunction() {
// ...
}
}
class derived {
/**
* each instance of `derived` *contains* an in instance of `base`
* that instance will be stored in this protected property
*/
protected $base;
/**
* constructor
*/
function __construct() {
// remember to call base's constructor
// passing along whatever parameters (if any) are needed
$this->base = new base();
// ... now do your constructor logic, if any ...
}
/**
* Here's the method that fetches the contained
* instance of `base`
*/
public function getBase() {
return $this->base;
}
/**
* If needed, `derived` can implement public elements
* from `base`'s interface. The logic can either delegate
* directly to the contained instance of base, or it can
* do something specific to `derived`, thus "overriding"
* `base`'s implementation.
*/
public function someBaseFunction() {
return $this->base->someBaseFunction();
}
/**
* of course, `derived` can implement its own public
* interface as well...
*/
public function someOtherFunction() {
}
}

In phpDoc, how do I write a class I don't know yet will be returned?

The following is code for Base.php and the class Base
/**
* #return ?
*/
public static function withId($id, $class = __CLASS__)
{
$instance = new $class($id);
if ($instance->getId() == self::ID_OF_UNKNOWN_USER) {
$instance = null;
}
return $instance;
}
Other classes will extend this class. I'm using late static binding to figure out who should be created prior to calling withId() and passing the class name as $class.
The returned class could be Base or any of its children. How do I mark that in phpDoc?
This looks somewhat like a factory pattern, in which case the user code shouldn't know the concrete class returned. Usually you'd use an abstract class or interface and program for that. In this case:
/**
* #return null|Base
*/
There's no way to use values generated at runtime in docstrings (which are static).
The returned class could be Base or any of its children. How do I mark that in phpDoc?
Straight forward.
/**
* #return Base
*/

Categories