Is it possible to overuse late static binding in PHP? - php

Starting with version 5.3, PHP supports late binding for static methods. While it's an undoubtedly useful feature, there are only several cases where its use is really necessary (e.g. the Active Record pattern).
Consider these examples:
1. Convenience constructors (::create())
class SimpleObject
{
public function __construct() { /* ... */ }
public static function create()
{
return new static; // or: return new self;
}
}
If this class may be extended (however, it's not extended by any class in the same package), should late static binding be used just to make extending it easier (without having to rewrite the ::create() method, and, more importantly, without having to remember to do that)?
Note: this idiom is used to work around the impossibility to call methods on just constructed objects: new SimpleObject()->doStuff() is invalid in PHP.
2. Class constants
class TagMatcher
{
const TAG_PATTERN = '/\<([a-z\-]+?)\>/i';
private $subject;
public function construct($subject) { $this->subject = $subject; }
public function getAllTags()
{
$pattern = static::TAG_PATTERN;
preg_match_all($pattern, $this->subject);
return $pattern[1];
}
}
The reason to use static:: in this example is similar to the previous one. It's used just because this class can be made to match differently formed tags just by extending it and overriding the constant.
So, to wrap it all up, are these uses (and similar ones) of late static binding are an overkill? Is there any noticeable performance hit? Also, does frequent use of late binding reduce the overall performance boost given by opcode caches?

So, to wrap it all up, are these uses (and similar ones) of late static binding are an overkill? Is there any noticeable performance hit? Also, does frequent use of late binding reduce the overall performance boost given by opcode caches?
The introduction of late static binding fixes a flaw in PHP's object model. It's not about performance, it's about semantics.
For example, I like to use static methods whenever the implementation of the method doesn't use $this. Just because a method is static doesn't mean to say that you don't want to override it sometimes. Prior to PHP 5.3, the behavior was that no error was flagged if you overrode a static method, but PHP would just go ahead and silently use the parent's version. For example, the code below prints 'A' before PHP 5.3. That's highly unexpected behavior.
Late static binding fixes it, and now the same code prints 'B'.
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>

static methods (early- or late-bound) create tight coupling and (thus) reduce testability. you can create large programs in PHP without using more than a few static calls. for me, late static methods are a non-feature.
edit to answer Marco Demaio's question, how do static method reduce testability?
i'm sorry if this is all obvious to you, static members (both data and methods) are useful and do no harm if used responsibly, i was alluding to their prevalent misuse.
say you have a web application that uses an SQL database. your business objects may retrieve data using a static interface or through polymorphism. either
class MyBusinessObject
extends...
{
public function doThisOrThat(...)
{
$results = db::query('sql string...');
...
}
}
or
class MyBusinessObject
extends...
{
public function __construct(dbconn $db)
{
$this->db = $db;
}
private $db;
public function doThisOrThat(...)
{
$results = $this->db->query('sql string...');
...
}
}
the latter is easier to test (as in: i want to test that the sql string constructed from such-and-such inputs is such-and-such) because it's easier to create another implementation of the dbconn interface than it is to change the meaning of db::. why you'd want either? because you don't need a real database to test the sql-composing behavior, and in fact it's easier to test for without a real database. also, it's easier to stub out the sql consumer if your tests are concerned with another aspect of the CUT (Code Under Test).
testing always implies lying to the tested code about its collaborators, and abstaining from static interfaces (the "doublecolon" or "quadridot") means the lie need not be a massive surgery, which is a plus, since the farther the tested code is from the production code, the less meaningful the test results are.

Where I find a need to use late static binding is to allow mocking of static methods for unit testing with PHPUnit. The problem I have is that I don't like changing code strictly to allow mocking, but I can get over that.
To answer your question, however, I would bet that whatever performance cost this carries, it will pale in comparison to most program runtimes. In other words, it won't make a noticeable difference.

Related

PHP static methods vs non-static methods/standard functions

I am working on a web app and writing pure OOP based PHP for the first time. And I have a question about static method VS standard function:
Here is an example scenario:
class Session
{
public function start_new_session()
{
session_start();
//other code here like token generator
}
}
VS
class Session
{
static function start_new_session()
{
session_start();
//other code here like token generator
}
}
Questions
What is the difference in both?
Which is better for my case?
Any application? (I mean, what are the best scenario to use static method and standard function)
My Research:
I spent some time to find the answer but don't found relevant answer however I found a lot of debate and useful material. Believe me it is super hard to decide (Who is right/wrong?) for a beginner like me:
In this question Someone said, It's horrible idea to use cookies in static functions and someone's saying It's a great idea
And in this question: Everyone is debating on performance and some experts are saying, the static functions execute faster and some saying; functions are faster. And result also vary because of different versions of php.
Some useful stat:
PHP 5.2 : static methods are ~10-15% faster.
PHP 5.3 : non-static methods are ~15% faster
PHP 5.4 : static methods are ~10-15% faster
PHP 5.5 : static methods are ~20% faster
To call a non-static method you need to instantiate the class (use the new keyword to create a new instance of the class).
When calling a static method you don't have to "new it up" but it won't have direct access to any of the non-static properties or methods. There are dozens of use-cases / scenarios where you might want to use one over the other.
To be quite honest it has never even crossed my mind to think about performance of using one over the other. If it got to a point where it made that much of a noticeable difference (and all major steps had been taken to increase efficiency) then I would imagine that either the maintenance costs of such a big application would outweigh the need for the increased efficiency or the logic behind the app is fairly flawed to begin with.
Examples for static and non-static
If I was going to use a class for the example in your question then I would use the static version as nothing in the method is reliant on other properties of the class and you then don't have to instantiate it:
Session::start_new_session()
vs
$session = new Session();
$session->start_new_session();
Also, static properties on a class will remember state that would have otherwise been lost if you were to use a non-static property and instantiation:
class Session
{
protected static $sessionStarted = false;
static function start_new_session()
{
if (!static::$sessionStarted) {
session_start();
static::$sessionStarted = true;
}
}
}
Then even if you did:
$session = new Session();
$hasStated = $session::sessionStarted;
$hasStarted would still be true.
You could even do something like:
class Session
{
protected static $sessionStarted = false;
public function __construct()
{
$this->startIfNotStarted();
}
function startIfNotStarted()
{
if (!static::$sessionStarted) {
session_start();
static::$sessionStarted = true;
}
}
}
This way you don't need to worry about starting the session yourself as it will be started when you instantiate the class and it will only happen once.
This approach wouldn't be suitable if you had something like a Person class though as the data would be different each time and you wouldn't want to use the same data in difference instantiations.
class Person
{
protected $firstname;
protected $lastname;
public function __construct($firstname, $lastname)
{
$this->firstname = $firstname;
$this->lastname = $lastname;
}
public function getFullname()
{
return "{$this->firstname} {$this->lastname}";
}
}
$person1 = new Person('John', 'Smith');
$person2 = new Person('Jane', 'Foster');
$person1->fullname(); // John Smith
$person2->fullname(); // Jane Foster
If you were to use static methods / properties for this class then you could only ever have one person
class Person
{
protected static $firstname;
protected static $lastname;
static function setName($firstname, $lastname)
{
static::$firstname = $firstname;
static::$lastname = $lastname;
}
static function getFullname()
{
return static::$firstname . ' ' . static::$lastname;
}
}
Person::setName('John', 'Smith');
Person::setName('Jane', 'Foster');
Person::getFullname(); //Jane Foster
The debates
You are probably going to see a lot of debates over which is better and what the best practices are when it comes to PHP (not just about static and not-static methods).
I wouldn't get bogged down with it though! If you find that one side makes more sense to you (and whatever you're building at the time) then go with that one. Standards and opinions change all the time in this community and half of the stuff that was a problem 5 years ago (or even less) will actually be non-issues today.
Take the Laravel framework as an example -- one of the (many) debates is that Facades are bad because they're static and make use of magic methods which is hard to test and debug. Facades are actually very easy to test and with the use of stack trace error reporting it isn't hard to debug at all. That's not to say their aren't caveats when it comes to testing static methods, but this is more to do with mocking/spying -- this answer goes into it in a little more detail.
That being said, if you find the majority of people are saying the same thing and there isn't really a debate for the other side, there is probably a reason e.g. don't use mysql_ functions or don't run queries inside a loops.

when to use static method or simple class method?

I am confused whether to use static method or just simple method.
Lets me give an example, I am using Zend framework 1 project.
I have class like
class Example1
{
public static function getVariable() {
return is_numeric(Zend_Registry::get('config')->Variable) ? Zend_Registry::get('config')->Variable : 0;
}
public function calculateSome($param1, $param2) {
$response = array();
if($param2 == 0) {
$response = number_format(($param1 * self::getvariable()) /100);
} else {
$response = $param1;
}
return $response;
}
}
Usage :
Currently i'm getting variable value like Example1::getVariable() in whole project.
And Calculating like first instantiating a class $class1 = new Example1(); and then calling the function like $class1->calculateSome(1, 0);
I am confused whether it is good to change calculateSome() to public static and call like this Example1::calculateSome(1, 0) or left as it is.
I Have found link when to use static =>
When to use static vs instantiated classes
But I can't understand what it says.
You can find the long answer here: How Not To Kill Your Testability Using Statics
The TL;DR version of it is:
A static method is nothing more than a namespaced function, Foo::bar() does not significantly differ from foo_bar().
Whenever you call a static method, or a function for that matter, you're hardcoding a dependency. The code that reads $bar = Foo::bar(); has a hardcoded dependency to a specific Foo class. It is not possible to change what Foo refers to without changing that part of the source code.
An object is a "soft" dependency. $bar = $foo->bar(); is flexible, it allows room to change what $foo refers to. You use this with dependency injection to decouple code from other code:
function baz(Foo $foo) {
$bar = $foo->bar();
...
}
You can call Foo::bar() anytime from anywhere. If Foo::bar has some dependency it depends on, it becomes hard to guarantee that this dependency is available at the time you're calling the method. Requiring object instantiation requires the object's constructor to run, which can enforce requirements to be set up which the rest of the methods of the object can depend on.
Constructors together with dependency injecting objects into other functions are very powerful to
create seams in your codebase to make it possible to "take it apart" and put it together in flexible ways
put checks into strategic places to ensure requirements are met for certain parts of the code (at object instantiation time the constructor enforces a sane state of its little part of the world, its object), which makes it a lot easier to localise and contain failures.
Think of it like compartmentalising your app and putting firewalls between each compartment with a supervisor in charge of each one; instead of everyone just running around in the same room.
Any time you write new Class, you may as well write Class::staticMethod(), the hardcoded dependency is the same.
So the decision comes down to:
What are the requirements of this class? Does it need to ensure certain preconditions are met before any of its code can run (e.g. a database connection needs to be available), or are all methods just self-contained little helper methods?
How likely are you to maybe want to substitute this class for another class? Does this class produce side effects (e.g. writing to a file, modifying some global state) which may not always be desirable and hence a different version of it may be useful under some circumstances?
May you need more than one instance of this class at the same time, or is the nature of the class such that there are no individual instances needed?
Start using unit tests, which require you to take your app apart and test each little part individually to ensure it works, and you'll see where the advantage of object instantiation and dependency injection lie.
When the method involve instance-based properties/changes u should keep it non-static.
If its a method that is needed for the whole type then use static.
For example u can keep tracks of created instances by this snippet:
class Product {
static $count;
private $name;
public function __construct($name) {
$this->name = $name;
self::$count++;
}
public function getName() {
return $this->name;
}
public static function getCount() {
return self:$count;
}
}
$productA = new Product('A');
$productB = new Product('B');
echo $productA->getName(). ' and ' . $productB->getName(). '<br />'. PHP_EOL;
echo 'Total made products :' . Product::getCount();

PHP: Retain static methods AND maintain testability

My static methods are either of the 'helper' variety, e.g. convertToCamelCase(), or of the 'get singleton' variety, e.g. getInstance(). Either way, I am happy for them to live in a helper class.
The helper class needs to be widely available so I am loading it in my layer supertypes. Now, as far as I can see, provided that the helper can be injected into the supertypes, I have maintained full flexibility over testing my code (with the exception of the helper class itself). Does that make sense? Or am I overlooking something?
To look at it another way... it seems to me that difficulty in testing code increases in proportion to the number of calls to static methods, not in proportion to actual number of static methods themselves. By putting all these calls into one class (my helper), and replacing that class with a mock, I am testing code that is free of static calls and related problems.
(I realise that I should work towards getting rid of my Singletons, but that's going to be a longer term project).
In the case of a static class that is strictly a helper function like "convertToCamelCase" I would probably just have 100% coverage for that function and then consider it a "core" function and not worry about mocking it elsewhere. What is a mock for "convertToCamelCase" going to do anyway..? Perhaps your unit tests start to smell a little like integrations tests if you do it too much, but there's always a bit of a tradeoff between abstracting everything and making your app needlessly complicated.
As far as singletons it is tricky because you usually have the name of the static class in your code so it becomes problematic to swap it out with a mock object for testing. One thing you could do is wherever you are making your static method calls, start by refactoring to call them this way:
$instance = call_user_func('MyClass::getinstance');
Then, as you increase your testing coverage, you could begin replacing with something like:
$instance = call_user_func($this->myClassName . '::getinstance');
So - once you have that, you could swap out and mock MyClass by changing $this->myClassName. You'd have to make sure you're requiring or autoloading the relevant php files dynamically as well.
Refactoring to use an abstract factory pattern would make things even easier to test but you could start implementing that over time as well
However if you need to mock a static class somewhere, you can do it with Moka library. Here is example:
class UsersController
{
public function main()
{
return json_encode(User::find(1));
}
}
This is how you can test it:
class UsersController
{
private $_userClass;
public function __construct($userClass = 'User')
{
$this->_userClass = $userClass;
}
public function find($id)
{
return json_encode($this->_userClass::find($id));
}
}
class UsersControllerTest extends \PHPUnit_Framework_TestCase
{
public function testMainReturnsUser()
{
$userClass = Moka::stubClass(null, ['::find' => 'USER']);
$controller = new UsersController($userClass);
$this->assertEquals('"USER"', $controller->find(1000));
}
public function testMainCallsFind()
{
$userClass = Moka::stubClass(null, ['::find' => 'USER']);
$controller = new UsersController($userClass);
$controller->find(1000);
// check that `find` was called with 100
$this->assertEquals([1000], $userClass::$moka->report('find')[0]);
}
}

How to use methods from another class in an object context?

I want to ask a noob question regarding the server performance.
Assume that each class contain 1000 line codes with same performance wight .
If I want to use a function belongs to the another. I found that there are 3 ways to do that.
Inside class $this->Another_Class = new Another_Class
Use static Another_Class::Wanted_Function()
Global global $Another_Class
May I ask in term of server performance, are they the same?? or do I have alternative except magic call?
I strongly suggest you do not use globals for anything.
As for whether to use static or instantiated classes... that's entirely up to what you're trying to do. A static member function is essentially the same as a namespaced function that has the ability to access other static member functions/variables.
Instantiating a class is technically slower than accessing a static class, but that's only the case if you have logic that is run when the __construct() and class variable initialization happens.
Globals should be avoided at all times, and static generally should be avoided too unless it is really necessary as they are not good for code reuse.
Also, you might want to take a look at such concepts as Inversion of Control and Dependency Injection.
In short you should prefer not to instantiate dependencies within class, but inject it.
Simple example:
class Example
{
protected $foo;
public function setFoo($foo)
{
$this->foo = $foo;
}
public function doSomething()
{
$this->foo->callFooMethod();
}
}
$example = new Example();
$example->setFoo(new Foo);
$example->doSomething();

How is testing the registry pattern or singleton hard in PHP?

Why is testing singletons or registry pattern hard in a language like PHP which is request driven?
You can write and run tests aside from the actual program execution, so that you are free to affect the global state of the program and run some tear downs and initialization per each test function to get it to the same state for each test.
Am I missing something?
While it's true that "you can write and run tests aside of the actual program execution so that you are free to affect the global state of the program and run some tear downs and initialization per each test function to get it to the same state for each test.", it is tedious to do so. You want to test the TestSubject in isolation and not spend time recreating a working environment.
Example
class MyTestSubject
{
protected $registry;
public function __construct()
{
$this->registry = Registry::getInstance();
}
public function foo($id)
{
return $this->doSomethingWithResults(
$registry->get('MyActiveRecord')->findById($id)
);
}
}
To get this working you have to have the concrete Registry. It's hardcoded, and it's a Singleton. The latter means to prevent any side-effects from a previous test. It has to be reset for each test you will run on MyTestSubject. You could add a Registry::reset() method and call that in setup(), but adding a method just for being able to test seems ugly. Let's assume you need this method anyway, so you end up with
public function setup()
{
Registry::reset();
$this->testSubject = new MyTestSubject;
}
Now you still don't have the 'MyActiveRecord' object it is supposed to return in foo. Because you like Registry, your MyActiveRecord actually looks like this
class MyActiveRecord
{
protected $db;
public function __construct()
{
$registry = Registry::getInstance();
$this->db = $registry->get('db');
}
public function findById($id) { … }
}
There is another call to Registry in the constructor of MyActiveRecord. You test has to make sure it contains something, otherwise the test will fail. Of course, our database class is a Singleton as well and needs to be reset between tests. Doh!
public function setup()
{
Registry::reset();
Db::reset();
Registry::set('db', Db::getInstance('host', 'user', 'pass', 'db'));
Registry::set('MyActiveRecord', new MyActiveRecord);
$this->testSubject = new MyTestSubject;
}
So with those finally set up, you can do your test
public function testFooDoesSomethingToQueryResults()
{
$this->assertSame('expectedResult', $this->testSubject->findById(1));
}
and realize you have yet another dependency: your physical test database wasn't setup yet. While you were setting up the test database and filled it with data, your boss came along and told you that you are going SOA now and all these database calls have to be replaced with Web service calls.
There is a new class MyWebService for that, and you have to make MyActiveRecord use that instead. Great, just what you needed. Now you have to change all the tests that use the database. Dammit, you think. All that crap just to make sure that doSomethingWithResults works as expected? MyTestSubject doesn't really care where the data comes from.
Introducing mocks
The good news is, you can indeed replace all the dependencies by stubbing or mock them. A test double will pretend to be the real thing.
$mock = $this->getMock('MyWebservice');
$mock->expects($this->once())
->method('findById')
->with($this->equalTo(1))
->will($this->returnValue('Expected Unprocessed Data'));
This will create a double for a Web service that expects to be called once during the test with the first argument to method findById being 1. It will return predefined data.
After you put that in a method in your TestCase, your setup becomes
public function setup()
{
Registry::reset();
Registry::set('MyWebservice', $this->getWebserviceMock());
$this->testSubject = new MyTestSubject;
}
Great. You no longer have to bother about setting up a real environment now. Well, except for the Registry. How about mocking that too. But how to do that. It's hardcoded so there is no way to replace at test runtime. Crap!
But wait a second, didn't we just say MyTestClass doesn't care where the data comes from? Yes, it just cares that it can call the findById method. You hopefully think now: why is the Registry in there at all? And right you are. Let's change the whole thing to
class MyTestSubject
{
protected $finder;
public function __construct(Finder $finder)
{
$this->finder = $finder;
}
public function foo($id)
{
return $this->doSomethingWithResults(
$this->finder->findById($id)
);
}
}
Byebye Registry. We are now injecting the dependency MyWebSe… err… Finder?! Yeah. We just care about the method findById, so we are using an interface now
interface Finder
{
public function findById($id);
}
Don't forget to change the mock accordingly
$mock = $this->getMock('Finder');
$mock->expects($this->once())
->method('findById')
->with($this->equalTo(1))
->will($this->returnValue('Expected Unprocessed Data'));
and setup() becomes
public function setup()
{
$this->testSubject = new MyTestSubject($this->getFinderMock());
}
Voila! Nice and easy and. We can concentrate on testing MyTestClass now.
While you were doing that, your boss called again and said he wants you to switch back to a database because SOA is really just a buzzword used by overpriced consultants to make you feel enterprisey. This time you don't worry though, because you don't have to change your tests again. They no longer depend on the environment.
Of course, you still you have to make sure that both MyWebservice and MyActiveRecord implement the Finder interface for your actual code, but since we assumed them to already have these methods, it's just a matter of slapping implements Finder on the class.
And that's it. Hope that helped.
Additional Resources:
You can find additional information about other drawbacks when testing Singletons and dealing with global state in
Testing Code That Uses Singletons
This should be of most interest, because it is by the author of PHPUnit and explains the difficulties with actual examples in PHPUnit.
Also of interest are:
TotT: Using Dependency Injection to Avoid Singletons
Singletons are Pathological Liars
Flaw: Brittle Global State & Singletons
Singletons (in all OOP languages, not just PHP) make a particular kind of debugging called unit testing difficult for the same reason that global variables do. They introduce global state into a program, meaning that you can't test any modules of your software that depend on the singleton in isolation. Unit testing should include only the code under test (and its superclasses).
Singletons are essentially global state, and while having global state can make sense in certain circumstances, it should be avoided unless it's necessary.
When finishing a PHP test, you can flush singleton instance like this:
protected function tearDown()
{
$reflection = new ReflectionClass('MySingleton');
$property = $reflection->getProperty("_instance");
$property->setAccessible(true);
$property->setValue(null);
}

Categories