PHP static keyword used with new in building an object - php

I am reading about Patterns in OOP and came across this code for the singleton pattern:
class Singleton
{
/**
* #var Singleton reference to singleton instance
*/
private static $instance;
/**
* gets the instance via lazy initialization (created on first usage)
*
* #return self
*/
public static function getInstance()
{
if (null === static::$instance) {
static::$instance = new static;
}
return static::$instance;
}
/**
* is not allowed to call from outside: private!
*
*/
private function __construct()
{
}
/**
* prevent the instance from being cloned
*
* #return void
*/
private function __clone()
{
}
/**
* prevent from being unserialized
*
* #return void
*/
private function __wakeup()
{
}
}
The part in question is static::$instance = new static;. What exactly does new static do or how does this example work. I am familiar with your average new Object but not new static. Any references to php documentation would help greatly.

basically that is a extendable class, and whenever you call getInstance() you will get a singleton of the whatever class you call it in (that extends this singleton class). If you only use it in one instance, you could hardcode the classname, or use new self if you had hardcoded this in your class.
Also, the singleton is regarded a anti-pattern, see the answer her for more details on this pattern why-is-singleton-considered-an-anti-pattern

Related

PhpStorm metadata file for repository classes

In our application, we use repositories for models that are fetched from the database. So, we have an abstract repository that knows about the database, has a loadById method to load a database record and an abstract getEntity method that creates an object for that specific repository. Example code:
abstract class EntityRepository {
/**
* #param int $id
* #return AbstractEntity
*/
public function loadById($id) {
$record = $this->db->loadById($id);
$entity = $this->getEntity();
return $this->inflate($record, $entity);
}
/**
* #return AbstractEntity
*/
protected abstract function getEntity();
}
class PeopleRepository extends EntityRepository {
protected function getEntity() {
return new PeopleEntity();
}
}
abstract class AbstractEntity {
private $id;
/**
* #return int
*/
public function getId() {
return $this->id;
}
/**
* #param int $id;
*/
public function setId($id) {
$this->id = $id;
}
}
class PeopleEntity extends AbstractEntity {
private $name;
/**
* #return string
*/
public function getName() {
return $this->name;
}
/**
* #param string $name;
*/
public function setName($name) {
$this->name= $name;
}
}
When using an instance of PeopleRepository and fetching a model through loadById, PhpStorm is not able to resolve the returned model to a concrete type, but provides only code completion for the functions of AbstractEntity. Is there any simple way to make it work?
In https://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Advanced+Metadata, I've only found ways to make it work for concrete classes and their functions. So, enumerating all repository classes and all their ways of creating an entity might work. But I'd love to see an abstract way of defining like "All instances of EntityRepository will return an entity of that type defined in getEntity() when loading an entity"
I doubt there's a blanket way of doing this. Even using PHPStorm meta you have to be explicit for each case. Perhaps the way of doing this is by doing something like adding a repository facade e.g.
class RepositoryFacade {
public static function __callStatic($method, $args) {
if ($args[0] == People::class) {
array_shift($args);
return new PeopleRepository()->{$method}(...$args);
}
}
}
Then you might be able to typehint this using:
override(RepositoryFacade::loadById(0), type(0));
Of course the facade is not really the best pattern to be using in general so I can see how this might not be ideal.

PHPDoc: document parent class method that always yields itself or descendant class?

Consider this code:
class ParentClass {
public static function generate($className = __CLASS__){
if(!$className) return new self();
else return new $className();
}
}
class ChildClass extends ParentClass {
/**
* #param string $className
* #return ChildClass
*/
public static function generate($className = __CLASS__) {
return parent::generate($className);
}
}
var_dump($ChildClass::generate()); // object(ChildClass)[1]
ChildClass::generate() returns an instance of ChildClass wherever I use it because I never provide a $className argument. Problem is that my IDE gives me a warning about the parent::generate() call not matching the documented return type:
I would like to make this warning go away by adding documentation to the parent method. I could do:
#return ParentClass | ChildClass
Adding this to the parent method works but that's not practical because there are many dozen children classes, and there could be many more in the future. I have tried both of the following:
#return static
#return $className
but that hasn't made the warning go away. Is there a PHPDoc approved way to indicate that the calling child class will always be returned? Or -- more accurately -- that a class of type $className will be returned? If not, is there a way that works even with just my IDE? (PhpStorm 2017.2)
Update
#gogaz comment below got me to think: it would be enough if a PHPDoc #return could indicate something like self | descendants
You can document parent class method and then just inherit that on a child class method.
class ParentClass
{
/**
* #param string $className
* #return ChildClass
*/
public static function generate($className = __CLASS__){
if(!$className) return new self();
else return new $className();
}
}
class ChildClass extends ParentClass
{
/**
* #inheritdoc
*/
public static function generate($className = __CLASS__) {
return parent::generate($className);
}
}
I hope that this will solve your problem.
UPDATE:
Another way to do this is by using interface that all classes will implement, so you could expect that your generate method will return some class that implements that interface.
/**
* ...
* #return MyCustomInterface
*/
If this doesn't solve your issue... Then, you can set return type as "mixed", this will suppress warning and it won't lie :) because your generate method can return any class you specify via argument...
/**
* ...
* #return mixed
*/
I've run across something similar (PHPStorm is more anal than PHP is on the subject). Unless there's some reason you HAVE to have it be specific to the child class, I would do this
class ParentClass {
/**
* #param string $className
* #return ParentClass
*/
public static function generate($className = __CLASS__){
if(!$className) return new self();
else return new $className();
}
}
Remember, your ChildClass is still an instance of ParentClass

Properly Testing a simple class with Private Methods

Description:
I have a simple class that creates a symlink to a directory of uploaded files that are only available to registered members. It uses the current users session id in order to generate the random directory for the user. Once the user logs out, the symlink is removed. I would like to unit test the functionality of the class.
Question:
How do I go about properly unit testing this class since most functions are private, and I don't see any reason to make them public?
Here is the code for the PHP class:
<?php
namespace Test\BackEnd\MemberBundle\Library;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class DirectoryProtector
{
/** #var SessionInterface $_session */
private $_session;
/** #var ContainerInterface $_kernel */
private $_kernel;
/**
* #param SessionInterface $session
* #param KernelInterface $kernel
*/
public function __construct( SessionInterface $session, KernelInterface $kernel )
{
$this->_session = $session;
$this->_kernel = $kernel;
}
/**
* #param bool|false $protect
* Public method to symlink directories
*/
public function protectDirectory($protect = FALSE)
{
if ($protect) {
if ( ! $this->doesDirectoryExists())
symlink($this->getAppDir() . '/uploads', $this->getViewableSessionDirectory());
} else {
if ($this->doesDirectoryExists())
unlink($this->getViewableSessionDirectory());
}
}
/**
* #return bool
* Check to see if viewable session directory exists or not
*/
private function doesDirectoryExists()
{
if (file_exists($this->getViewableSessionDirectory()))
return TRUE;
return FALSE;
}
/**
* #return string
* Get viewable session full directory path
*/
private function getViewableSessionDirectory()
{
return $this->getAppDir() . '/../web/files/' . $this->getSessionId();
}
/**
* #return string
* Return app root directory
*/
private function getAppDir()
{
return $this->_kernel->getRootDir();
}
/**
* #return string
* Return session id
*/
private function getSessionId()
{
return $this->_session->getId();
}
}
Here is the code for the current test class:
<?php
namespace Test\BackEnd\MemberBundle\Tests\Library;
use Test\BackEnd\MemberBundle\Library\DirectoryProtector;
class DirectoryProtectorTest extends \PHPUnit_Framework_TestCase
{
public function testProtectDirectory()
{
//$this->markTestIncomplete("WIP on protect directory.");
$request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')
->getMock();
$container = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')
->getMock();
/** #var DirectoryProtector $dp */
$dp = $this->getMockBuilder('Test\BackEnd\MemberBundle\Library\DirectoryProtector')
->setConstructorArgs(array($request, $container))
->setMethods(array(
'getViewableSessionDirectory',
'getAppDir',
'getSessionId'
))
->getMock();
$dp->expects($this->once())
->method('doesDirectoryExists')
->will($this->returnValue(TRUE));
$dp->protectDirectory(TRUE);
}
}
From https://phpunit.de/manual/current/en/test-doubles.html
Limitation: final, private, and static methods
Please note that final, private and static methods cannot be stubbed or mocked. They are ignored by PHPUnit's test double functionality and retain their original behavior.
Is not a good practice to unit test private or protected methods. You should test the public API. Private methods are supposed to be tested indirectly through the API. That said, you can make the method public with reflection:
$instance = new DirectoryProtector(...);
$ref = new \ReflectionClass('DirectoryProtector');
$method = $ref->getMethod('doesDirectoryExists');
$method->setAccessible(true);
$this->assertTrue($method->invoke($instance));
I think your approach is incorrect. You shouldn't mock method, but objects that are passed by injection in constructor.
For the SessionInterface you can pass MockArraySessionStorage. For ContainerInterface I don't know which class you are using, so I add some demo example. Test case:
public function testProtectDirectory()
{
$session = new MockArraySessionStorage();
$session->setId('123123');
$kernel = \Ouzo\Tests\Mock\Mock::create('ContainerInterface');
\Ouzo\Tests\Mock\Mock::when($kernel)->getRootDir()->thenReturn('/root_dir');
$directoryProtector = new DirectoryProtector($session, $kernel);
$directoryProtector->protectDirectory(true);
//asserts
}
and your methods will be returning:
getViewableSessionDirectory -> /root_dir/../web/files/123123
getAppDir -> /root_dir
And remember changing methods accessible is always bad idea.
PS. For mocking I use utils form Ouzo framework. Of course you can use other mocking framework.

PHP docstring #return type for subclass of current class

What is the canonical #return type for a static method of a parent class that returns an instance of a subclass, undetermined at time of writing? For example:
<?php
class Thing {
/**
* Do something
*
* #return ??? Instance of some new class.
*/
public static function create_subclass($class) {
return new $class();
}
}
class Person extends Thing {}
$person = Thing::create_subclass('Person');
?>
It seems like this shouldn't be #return self because it's returning a subclass of self, and specifying all possible return classes would be silly. Any ideas?
You can use #return Thing or #return Person|AnotherClass|AnotherClass

requires polymorphic singleton example in php

show me please example of the polymorphic sigleton in php.
google found very few mentions about this and all in C which is not clear to me
Here you go:
/**
* Base class for Polymorphic Singleton.
*/
class Polymorphic_Singleton {
/**
* #var Polymorphic_Singleton
*/
private static $__instance = null;
private static $__instance_class_name = "";
/**
* Gets an instance of Polymorphic_Singleton/
*
* Uses a Polymorphic Singleton design pattern. Maybe an anti-pattern. Discuss amongst yourselves.
*
* Can be called by a subclass, and will deliver an instance of that subclass, which most Singletons don't do.
* You gotta love PHP.
*
* #return Polymorphic_Singleton
*/
final public static function get_instance(){
if ( ! isset( self::$__instance ) ){
self::$__instance_class_name = get_called_class();
self::$__instance = new self::$__instance_class_name(); // call the constructor of the subclass
}
return self::$__instance;
}
/**
* Don't ever call this directly. Always use Polymorphic_Singleton ::get_instance()
*
* #throws Exception if called directly
*/
public function __construct(){
if ( ! self::$__instance ){
// do constructor stuff here...
} else {
throw new Exception( "Use 'Polymorphic_Singleton ::get_instance()' to get a reference to this class.", 100 );
}
}
}
I don't clearly understand what you meant by "polymorphic singleton". The singleton pattern itself has been explained in many places out there, for instance:
http://en.wikipedia.org/wiki/Singleton_pattern
In PHP, you can achieve singleton pattern using this simple code:
<?php
class Something
{
private static $instance;
private function __construct() {}
private function __clone() {}
public static function getInstance()
{
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
}
// how to use
$instance1 = Something::getInstance();
$instance2 = Something::getInstance();
var_dump($instance1 === $instance2); // returns true proving that getInstance returns identical instance

Categories