我正在开发一个Web应用程序,并且第一次编写基于OOP的纯PHP。我有一个关于静态方法VS标准函数的问题:
下面是一个示例方案:
class Session
{
public function start_new_session()
{
session_start();
//other code here like token generator
}
}
与
class Session
{
static function start_new_session()
{
session_start();
//other code here like token generator
}
}
问题
- 两者有什么区别?
- 哪个更适合我的情况?
- 任何应用?(我的意思是,使用静态方法和标准函数的最佳方案是什么)
我的研究:
我花了一些时间寻找答案,但没有找到相关的答案,但我找到了很多辩论和有用的材料。相信我,对于像我这样的初学者来说,很难决定(谁对谁错?):
在这个问题中,有人说,在静态函数中使用cookie是个可怕的主意,有人说这是一个好主意
在这个问题上:每个人都在争论性能,一些专家说,静态函数执行得更快,有些人说;函数执行得更快。结果也因不同版本的 php 而有所不同。
一些有用的统计数据:
PHP 5.2: 静态方法快 ~10-15%。
PHP 5.3: 非静态方法快 ~15%
PHP 5.4: 静态方法快 ~10-15%
PHP 5.5: 静态方法快 ~20%
要调用非静态方法,您需要实例化该类(使用new
关键字创建该类的新实例)。
调用静态方法时,您不必"新建它",但它不会直接访问任何非静态属性或方法。有几十个用例/场景,你可能想使用一个而不是另一个。
老实说,我什至从未想过使用一种而不是另一种的性能。如果它达到了一个如此显着的差异(并且已经采取了所有主要步骤来提高效率),那么我会想象,要么如此大的应用程序的维护成本将超过提高效率的需求,要么应用程序背后的逻辑一开始就存在相当大的缺陷。
静态和非静态示例
如果我打算在您的问题中的示例中使用一个类,那么我将使用静态版本,因为该方法中的任何内容都不依赖于该类的其他属性,然后您不必实例化它:
Session::start_new_session()
与
$session = new Session();
$session->start_new_session();
此外,类上的静态属性将记住如果使用非静态属性和实例化时会丢失的状态:
class Session
{
protected static $sessionStarted = false;
static function start_new_session()
{
if (!static::$sessionStarted) {
session_start();
static::$sessionStarted = true;
}
}
}
然后,即使您这样做了:
$session = new Session();
$hasStated = $session::sessionStarted;
$hasStarted
仍然会true
.
您甚至可以执行以下操作:
class Session
{
protected static $sessionStarted = false;
public function __construct()
{
$this->startIfNotStarted();
}
function startIfNotStarted()
{
if (!static::$sessionStarted) {
session_start();
static::$sessionStarted = true;
}
}
}
这样,您无需担心自己启动会话,因为它将在您实例化类时启动,并且只会发生一次。
如果你有一个类似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}";
}
}
$person1 = new Person('John', 'Smith');
$person2 = new Person('Jane', 'Foster');
$person1->fullname(); // John Smith
$person2->fullname(); // Jane Foster
如果你要对这个类使用静态方法/属性,那么你只能有一个人
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
辩论
你可能会看到很多关于PHP哪个更好以及最佳实践是什么的争论(不仅仅是静态和非静态方法)。
不过,我不会为此陷入困境!如果你发现一方对你更有意义(无论你当时正在构建什么),那就选择那一面。在这个社区中,标准和观点一直在变化,5年前(甚至更少)有一半问题的东西今天实际上不再是问题。
以Laravel
框架为例 - 其中一个(许多)争论是外墙不好,因为它们是静态的,并且使用了难以测试和调试的神奇方法。外观实际上非常容易测试,并且通过使用堆栈跟踪错误报告,调试起来一点也不难。这并不是说他们在测试静态方法时没有警告,但这更多地与嘲笑/间谍有关 - 这个答案更详细地介绍了它。
话虽如此,如果你发现大多数人都在说同样的事情,并且对方并没有真正的争论,那么可能有一个原因,例如不使用mysql_
函数或不在循环中运行查询。