📜 ⬆️ ⬇️

Recursion with self

Interesting and sometimes unusual properties hide from documenting the fifth version of PHP. The self language construct is, by definition, used to work with static methods and class properties. But it can be used for other purposes.

I declare myself ...


Many people faced the problem of renaming a class (You forget to rename the constructor, but there is no error and everything seems to work, but it’s somehow crooked). To solve this problem, PHP5 introduced a standard name for constructors __construct
This problem can be even easier if you use self to declare a new instance of the class. For example:
class Spadar_Core_Object
{
/ **
* Single class instance
*
* @staticvar Spadar_Core_Object
* /
private static $ oInstance;

...
')
/ **
* Get a single instance of a class (singleton design pattern)
*
* return Spadar_Core_Object singleton instance
* /
public static function getInstance ()
{
if (! isset (self :: $ oInstance))
{
self :: $ oInstance = new self ();
}

return self :: $ oInstance;
}

...

}


Now you should not worry about the class name. However, in this case, we do not receive much benefit from such an announcement.
Next, let's imagine ourselves as cool developers of a cool library. And now all classes for which we want to use a single object must for this will be inherited from Spadar_Core_Object. We modify the class code a bit:

class Spadar_Core_Object
{
/ **
* Single instances of classes of heirs
*
* @staticvar array
* /
private static $ aInstances = array () ;

...

/ **
* Get a single instance of a descendant class (singleton design pattern)
*
* return Spadar_Core_Object singleton instance
* /
public static function getInstance ()
{
if (! isset ( self :: $ aInstances [__ CLASS__] ))
{
self :: $ aInstances [__ CLASS__] = new self ();
}

return self :: $ aInstances [__ CLASS__];
}

...

}


There is an alternative option: instead of new self, get the $ sClassName = __CLASS__ variable; and declare it like this: new $ sClassName ();

Type Parameter Check


In PHP5, you can specify a type for method parameters. Including self as type

class Spadar_Controller_Widget extends Spadar_Core_Object
{
/ **
* Feeds on child widgets
*
* var array
* /
protected $ aChildWidgets = array ();
...

/ **
* Adding a child to the Widget
*
* param Spadar_Controller_Widget $ oWidget new child
* return Spadar_Controller_Widget the callee for subsequent operations
* /
public function addChild ( self $ oWidget )
{
$ this-> aChildWidgets [] = $ oWidget;

return $ this;
}

...

}


In this example, a tree is built from objects; for this, its children are transferred to each object; they must be of a certain type.

Is it me or not me?


Back to writing a hyper-library in PHP. Suppose that information is stored in some packet through seralization. In order to work with it correctly, we need to check whether it matches the specified interface:

class Spadar_Core_Object
{
...

/ **
* Object recovery
*
* param string $ sInfo
* return Spadar_Core_Object called object for subsequent operations
* /
private function parseObject ($ sInfo)
{
$ mInfo = $ sInfo;
$ mInfo = @unserialize ($ sInfo);

if ( $ mInfo instanceof self )
{
return $ mInfo;
}

return $ this;
}

...

}


About Constants ...



Class constants can be used not only in the usual way inside the body of methods, but also to be perverted with them a little:

class Spadar_Controller_Url extends Spadar_Core_Object
{
const PARSE_PROTOCOL = 'scheme';
const PARSE_HOST = 'host';
...
const BROWSER_ARG_PROTOCOL = self :: PARSE_PROTOCOL;

/ **
* What parameter to get from urla
*
* param string $ sParam parameter for getting from URL
* return string parameter value
* /
public function getParam ($ sParam = self :: PARSE_HOST )
{
...
}

...

}

We need to remember:


Source: https://habr.com/ru/post/15932/


All Articles