PHP Static Function

php static function

In the first class, sayHi() is actually an instance method which you are calling as a static method and you get away with it because sayHi() never refers to $this.

Static functions are associated with the class, not an instance of the class. As such, $this is not available from a static context ($this isn't pointing to any object).

When should I use static methods?

It is an interesting subject. I'm gonna give you a design oriented answer.

In my opinion, you should never use a static class/function in a good OOP architecture.

When you use static, this is to call a function without an instance of the class. The main reason is often to represent a service class which should not be instantiated many times.

I will give you 3 solutions (from the worst to the best) to achieve that:

Static

A static class (with only static functions) prevent you from using many OOP features like inheritance, interface implementation. If you really think of what is a static function, it is a function namespaced by the name of its class. You already have namespaces in PHP, so why add another layer?

Another big disadvantage is that you cannot define clear dependencies with your static class and the classes using it which is a bad thing for maintenability and scalability of your application.

Singleton

A singleton is a way to force a class to have only one instance:

<?php

class Singleton {
// Unique instance.
private static $instance = null;

// Private constructor prevent you from instancing the class with "new".
private function __construct() {
}

// Method to get the unique instance.
public static function getInstance() {
// Create the instance if it does not exist.
if (!isset(self::$instance)) {
self::$instance = new Singleton();
}

// Return the unique instance.
return self::$instance;
}
}

It is a better way because you can use inheritance, interfaces and your method will be called on an instanciated object. This means you can define contracts and use low coupling with the classes using it. However some people consider the singleton as an anti pattern especially because if you want to have 2 or more instances of your class with different input properties (like the classic example of the connection to 2 different databases) you cannot without a big refactoring of all your code using the singleton.

Service

A service is an instance of a standard class. It is a way to rationalize your code. This kind of architecture is called SOA (service oriented architecture). I give you an example:

If you want to add a method to sell a product in a store to a consumer and you have classes Product, Store and Consumer. Where should you instantiate this method? I can guarantee that if you think it is more logical in one of these three class today it could be anything else tomorrow. This leads to lots of duplications and a difficulty to find where is the code you are looking for. Instead, you can use a service class like a SaleHandler for example which will know how to manipulate your data classes.

It is a good idea to use a framework helping you to inject them into each others (dependency injection) in order to use them at their full potential. In the PHP community, you have a nice example of implementation of this in Symfony for instance.


To sum up:

  • If you do not have a framework, singletons are certainly an option even if I personally prefer a simple file where I make manual dependency injection.

  • If you have a framework, use its dependency injection feature to do that kind of thing.

  • You should not use static method (in OOP). If you need a static method in one of your class, this means you can create a new singleton/service containing this method and inject it to the instance of classes needing it.

PHP static methods vs non-static methods/standard functions

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.

How to call a non-static method from a static function in a class in php

Just create an instance:

    public static function staticFun ($data) {
$instance = new ClassName($data);
echo $instance->anotherFun($data);
}

Note: you have a parameter $data for anotherFun, but you don't use it anywhere.

PHP: Static method in Class vs Global function in Namespace?

Is there any reason to prefer one method over the other?

(below assumes you're asking/referring to a difference between a static class method and a function in a namespace)

Historically (before namespaces arrived), people were forced to use classes with static functions to not pollute a global namespace. This is one of the reasons you're likely to encounter this method more often.

You might prefer to use a static method if you need access to class's data or if you think of leaving a door to overriding them in descendant classes (the so-called 'flexibility and functionality' by some).

You might prefer a namespaced function when all you want is ...uh, ahem... a function. Think of some util, functional or collections functions like compose/partial, retry , filter/map/some/every etc. You are probably not expecting this to be overwritten in a child class, right? Neither it need access to some static class member.

There is one particular annoying problem with (namespaced) functions though, that classes don't suffer from. And it's autoloading. To put it short, there is no way to autoload a function at the moment. And this is another reason you'd likely encounter classes with static methods (when they don't necessarily need to be) more often in practice.



Related Topics



Leave a reply



Submit