get_called_class or new Static?

Asked

Viewed 204 times

6

I don’t remember which PHP library I saw this, but there was a code snippet where, to get a new instance of the current class, the function was used get_called_class.

But PHP has the keyword static, referring to late Static Binding.

It seems that the use of both produces the same result.

Behold:

class Yea
{
    public static function withStatic()
    {
        return new static;
    }

    public static function withCalledClass()
    {
        $class = get_called_class();
        return new $class;
    }
}


var_dump(Yea::withStatic());
var_dump(Yea::withCalledClass());

Since the output is the same, why some prefer to use get_called_class, instead of static?

IDEONE

  • It would be because get_called_class be available from php5.3 forward? tests this code on https://3v4l.org/ it will run in several versions of php. + 1

  • PHP 5.3 funfou https://3v4l.org/rmmvc

  • And in 5.2 down? gave error or gave another result? do not have access ...

  • It showed no results.

2 answers

5

The function get_called_class() returns the name class, while static returns the class itself.

From PHP 5.5, you can also use static::class to return the class name.

I believe it’s more a matter of style, but I would recommend using the static (especially if your goal is to instantiate the class, as in your example), for two reasons:

  • 1) It’s Shorter, your code gets cleaner;
  • 2) Performance. Although almost imperceptible, any function call costs.

You can make a simple comparison like this:

class Foo {
    public static function bar()
    {
        echo "\n get_called_class: ";
        $time = microtime(true);
        echo get_called_class(). ' ';
        printf('%f', microtime(true) - $time);

        echo "\n static: ";
        $time = microtime(true);
        echo static::class . ' ';
        printf('%f', microtime(true) - $time);
    }
}

echo "<pre>";
Foo::bar();

Upshot:

get_called_class: Bar 0.000006

Static: Bar 0.000001

These times may vary a little on each page load.

  • I liked your answer. But you know if the version question can influence when using a framework get_called_class or static?

  • Frameworks usually define a minimal version. This information is usually on the first page of the documentation, or in the "Installation" section. In short, the version does. If you are developing a framework of your own, then you have to choose whether you want to support only the most modern versions, or maintain compatibility with previous versions.

  • Always determined PHP 5.4 ++

  • Probably, this lib you saw wanted to get the name of the class in versions prior to 5.5. There are other options to do this too, such as the variable __CLASS__ or get_class($this) (if the method is not static)

3


It is worth noting that the function get_called_class came into existence from the version 5.3 of PHP.

In addition to the difference of performances as cited by Rafael

class Foo {
    public static function bar()
    {
        echo "\n get_called_class: ";
        $time = microtime(true);
        echo get_called_class(). ' ';
        printf('%f', microtime(true) - $time);

        echo "\n static: ";
        $time = microtime(true);
        echo static::class . ' ';
        printf('%f', microtime(true) - $time);
    }
}

echo "<pre>";
Foo::bar();

Upshot:

get_called_class: Bar 0.000006

static: Bar 0.000001

There is another issue that needs to be raised. The get_called_class is used in partnership with late static binding frameworks. For example, when a search framework uses a service system Locator/Ioc, they use the get_called_class, because this function returns the class name and this can be used to check if there are already instances together with the use of Factorypattern

Example

class Factory
{
    private static $_instances = array();

    public static function getInstance()
    {
        $class = get_called_class();
        if (!isset(self::$_instances[$class])) {
            self::$_instances[$class] = new $class();
        }
        return self::$_instances[$class];
    }
}

class ClassExtendFactory extends Factory {}

$class = ClassExtendFactory::getInstance();
$otherClass = ClassExtendFactory::getInstance();
var_dump($class === $otherClass);
// result true { ou seja, representam o mesmo objeto, duas variáveis apontando para o mesmo endereço de alocamento da memória }

When not using Factory, only use the late static binding

abstract class AbstractExample {
    public static function getInstance() {
        return new static();
    }
}

class Example extends AbstractExample {

}

$ex1 = Example::getInstance();
$ex2 = Example::getInstance();
var_dump($ex1 === $ex2);
// return false { ou seja, agora são 2 instâncias diferentes da mesma class, duas variáveis apontando para espaços diferentes de alocamento na memória }

That’s it, I hope it helped you understand a little better.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.