关于PHP:如何初始化静态变量

How to initialize static variables

我有这个代码:

1
2
3
4
5
6
private static $dates = array(
  'start' => mktime( 0,  0,  0,  7, 30, 2009),  // Start date
  'end'   => mktime( 0,  0,  0,  8,  2, 2009),  // End date
  'close' => mktime(23, 59, 59,  7, 20, 2009),  // Date when registration closes
  'early' => mktime( 0,  0,  0,  3, 19, 2009),  // Date when early bird discount ends
);

这给了我以下错误:

Parse error: syntax error, unexpected '(', expecting ')' in /home/user/Sites/site/registration/inc/registration.class.inc on line 19

所以,我想我做错了什么…但如果不喜欢的话,我该怎么做呢?如果我用常规字符串更改mktime,它会起作用。所以我知道我可以这样做……

有人有什么建议吗?


PHP无法分析初始值设定项中的重要表达式。

我更喜欢在类定义之后添加代码来解决这个问题:

1
2
3
4
class Foo {
  static $bar;
}
Foo::$bar = array();

1
2
3
4
5
6
7
8
class Foo {
  private static $bar;
  static function init()
  {
    self::$bar = array();
  }
}
Foo::init();

php 5.6现在可以处理一些表达式。

1
2
3
4
5
6
7
8
9
10
11
/* For Abstract classes */
abstract class Foo{
    private static function bar(){
        static $bar = null;
        if ($bar == null)
            bar = array(...);
        return $bar;
    }
    /* use where necessary */
    self::bar();
}


如果您可以控制类的加载,那么可以从那里进行静态初始化。

例子:

1
class MyClass { public static function static_init() { } }

在类加载器中,执行以下操作:

1
2
include($path . $klass . PHP_EXT);
if(method_exists($klass, 'static_init')) { $klass::staticInit() }

一个更重的解决方案是使用ReflectionClass接口:

1
2
interface StaticInit { public static function staticInit() { } }
class MyClass implements StaticInit { public static function staticInit() { } }

在类加载器中,执行以下操作:

1
2
$rc = new ReflectionClass($klass);
if(in_array('StaticInit', $rc->getInterfaceNames())) { $klass::staticInit() }


我宁愿简单地创建一个getter函数,而不是找到一种让静态变量工作的方法。如果您需要属于某个特定类的数组,并且实现起来要简单得多,那么它也很有用。

1
2
3
4
5
6
7
8
9
10
11
class MyClass
{
   public static function getTypeList()
   {
       return array(
          "type_a"=>"Type A",
          "type_b"=>"Type B",
           //... etc.
       );
   }
}

只要您需要列表,只需调用getter方法。例如:

1
2
3
if (array_key_exists($type, MyClass::getTypeList()) {
     // do something important...
}


我结合了特杰德·维瑟和波内尔的回答。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Something
{
    private static $foo;

    private static getFoo()
    {
        if ($foo === null)
            $foo = [[ complicated initializer ]]
        return $foo;
    }

    public static bar()
    {
        [[ do something with self::getFoo() ]]
    }
}

但更好的解决方案是去掉静态方法并使用单例模式。然后在构造函数中进行复杂的初始化。或者让它成为一个"服务",并使用DI将其注入到任何需要它的类中。


这太复杂了,无法定义。但是,您可以将定义设置为空,然后在构造函数中检查它,如果它没有被更改-设置它:

1
2
3
4
5
6
7
private static $dates = null;
public function __construct()
{
    if (is_null(self::$dates)) {  // OR if (!is_array(self::$date))
         self::$dates = array( /* .... */);
    }
}


在这部分代码中不能进行函数调用。如果您使init()类型的方法在任何其他代码之前执行,那么您将能够填充变量。


在php 7.0.1中,我可以定义:

1
2
3
4
public static $kIdsByActions = array(
  MyClass1::kAction => 0,
  MyClass2::kAction => 1
);

然后这样使用:

1
MyClass::$kIdsByActions[$this->mAction];

最好的方法是创建这样的访问器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @var object $db : map to database connection.
*/

public static $db= null;

/**
* db Function for initializing variable.  
* @return object
*/

public static function db(){
 if( !isset(static::$db) ){
  static::$db= new \Helpers\MySQL( array(
   "hostname"=>"localhost",
   "username"=>"root",
   "password"=>"password",
   "database"=>"db_name"
    )
  );
 }
 return static::$db;
}

然后您可以在任何地方执行static::db();或self::db()。


在代码示例中,这里有一个非常有用的指针。注意初始值设定项函数如何只调用一次。

另外,如果您反转对StaticClass::initializeStStateArr()$st = new StaticClass()的调用,您将得到相同的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$ cat static.php
<?php

class StaticClass {

  public static  $stStateArr = NULL;

  public function __construct() {
    if (!isset(self::$stStateArr)) {
      self::initializeStStateArr();
    }
  }

  public static function initializeStStateArr() {
    if (!isset(self::$stStateArr)) {
      self::$stStateArr = array('CA' => 'California', 'CO' => 'Colorado',);
      echo"In" . __FUNCTION__."
"
;
    }
  }

}

print"Starting...
"
;
StaticClass::initializeStStateArr();
$st = new StaticClass();

print_r (StaticClass::$stStateArr);

收益率:

1
2
3
4
5
6
7
8
$ php static.php
Starting...
In initializeStStateArr
Array
(
    [CA] => California
    [CO] => Colorado
)