PHP 静态方法与非静态方法/标准函数

Ale*_*ena 3 php oop

我正在开发一个 Web 应用程序并第一次编写基于纯 OOP 的 PHP。我有一个关于静态方法VS标准函数的问题:

这是一个示例场景:

class Session
{
    public function start_new_session()
    {
        session_start();
        //other code here like token generator
    }
}
Run Code Online (Sandbox Code Playgroud)

VS

class Session
{
    static function start_new_session()
    {
        session_start();
        //other code here like token generator
    }
}
Run Code Online (Sandbox Code Playgroud)

问题

  1. 两者有什么区别?
  2. 哪个更适合我的情况?
  3. 有什么应用吗?(我的意思是,使用静态方法和标准函数的最佳场景是什么)

我的研究:

我花了一些时间来寻找答案,但没有找到相关的答案,但是我发现了很多辩论和有用的材料。相信我,对于像我这样的初学者来说,很难决定(谁对谁错?):

  1. 在这个问题中有人说,在静态函数中使用 cookie 是一个可怕的想法,有人说这是一个好主意

  2. 在这个问题:每个人都在讨论对性能和一些专家说,静态函数执行速度更快,有的说; 功能更快。并且结果也因php版本不同而有所不同。

一些有用的统计数据:

PHP 5.2:静态方法快了大约 10-15%。

PHP 5.3:非静态方法快了约 15%

PHP 5.4:静态方法快了约 10-15%

PHP 5.5:静态方法快了约 20%

Rwd*_*Rwd 8

要调用非静态方法,您需要实例化类(使用new关键字创建类的新实例)。

调用静态方法时,您不必“对其进行更新”,但它无法直接访问任何非静态属性或方法。有许多用例/场景,您可能希望使用其中一个。

老实说它甚至从来没有穿过我的脑海考虑性能使用一个比其他的。如果它达到了如此显着差异的程度(并且已经采取了所有主要步骤来提高效率),那么我会想象这样一个大型应用程序的维护成本将超过提高效率的需要,或者该应用程序背后的逻辑一开始就存在相当大的缺陷。


静态和非静态示例

如果我打算在您的问题中为示例使用一个类,那么我将使用静态版本,因为该方法中的任何内容都不依赖于该类的其他属性,然后您不必实例化它:

Session::start_new_session()
Run Code Online (Sandbox Code Playgroud)

对比

$session = new Session();

$session->start_new_session();
Run Code Online (Sandbox Code Playgroud)

此外,类上的静态属性将记住如果您使用非静态属性和实例化可能会丢失的状态:

class Session
{
    protected static $sessionStarted = false;

    static function start_new_session()
    {
        if (!static::$sessionStarted) {
            session_start();
            static::$sessionStarted = true;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么即使你做了:

$session = new Session();

$hasStated = $session::sessionStarted;
Run Code Online (Sandbox Code Playgroud)

$hasStarted仍然会true

你甚至可以做这样的事情:

class Session
{
    protected static $sessionStarted = false;

    public function __construct()
    {
        $this->startIfNotStarted();
    }

    function startIfNotStarted()
    {
        if (!static::$sessionStarted) {

            session_start();

            static::$sessionStarted = true;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样您就不必担心自己启动会话,因为它会在您实例化类时启动,并且只会发生一次。

如果您有Person类之类的东西,这种方法将不适合,因为数据每次都会不同,并且您不想在不同的实例化中使用相同的数据。

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}";
    }
}
Run Code Online (Sandbox Code Playgroud)

//

$person1 = new Person('John', 'Smith');
$person2 = new Person('Jane', 'Foster');

$person1->fullname(); // John Smith
$person2->fullname(); // Jane Foster
Run Code Online (Sandbox Code Playgroud)

如果您要为此类使用静态方法/属性,那么您只能拥有一个人

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

//

Person::setName('John', 'Smith');
Person::setName('Jane', 'Foster');

Person::getFullname(); //Jane Foster
Run Code Online (Sandbox Code Playgroud)

辩论

您可能会看到很多关于 PHP 哪个更好以及最佳实践的争论(不仅仅是关于静态和非静态方法)。

不过,我不会陷入困境!如果你发现一侧对你更有意义(以及你当时建造的任何东西),那就选择那一侧。在这个社区中,标准和意见一直在变化,5 年前(甚至更少)存在的问题中有一半在今天实际上不再是问题。

Laravel框架为例——(许多)争论之一是外观不好,因为它们是静态的,并且使用了难以测试和调试的魔术方法。Facades 实际上很容易测试,并且使用堆栈跟踪错误报告根本不难调试。

话虽如此,如果您发现大多数人都在说同样的话,而另一方并没有真正进行辩论,那么可能是有原因的,例如不使用mysql_函数或不在循环内运行查询。

希望这可以帮助!