Как инициализировать статические переменные

У меня есть этот код:

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 ); 

Который дает мне следующую ошибку:

Ошибка анализа: синтаксическая ошибка, неожиданная '(', ожидающая ')' в /home/user/Sites/site/registration/inc/registration.class.inc в строке 19

Итак, я думаю, что я делаю что-то неправильно … но как я могу это сделать, если не так? Если я изменю файл mktime с помощью регулярных строк, он будет работать. Поэтому я знаю, что я могу так поступить.

У кого-нибудь есть указатели?

PHP не может анализировать нетривиальные выражения в инициализаторах.

Я предпочитаю обойти это, добавив код сразу после определения класса:

 class Foo { static $bar; } Foo::$bar = array(…); 

или

 class Foo { private static $bar; static function init() { self::$bar = array(…); } } Foo::init(); 

PHP 5.6 теперь может обрабатывать некоторые выражения.

Если у вас есть контроль над загрузкой классов, вы можете сделать статическую инициализацию оттуда.

Пример:

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

в загрузчике классов выполните следующие действия:

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

Более тяжелым решением будет использование интерфейса с ReflectionClass:

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

в загрузчике классов выполните следующие действия:

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

Вместо того, чтобы найти способ заставить статические переменные работать, я предпочитаю просто создавать функцию getter. Также полезно, если вам нужны массивы, принадлежащие к определенному классу, и намного проще реализовать.

 class MyClass { public static function getTypeList() { return array( "type_a"=>"Type A", "type_b"=>"Type B", //... etc. ); } } 

Везде, где вам нужен список, просто вызовите метод getter. Например:

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

Это слишком сложно установить в определении. Вы можете установить определение в значение null, но, а затем в конструкторе, проверьте его, и если он не был изменен – ​​установите его:

 private static $dates = null; public function __construct() { if (is_null(self::$dates)) { // OR if (!is_array(self::$date)) self::$dates = array( /* .... */); } } 

Я использую комбинацию Tjeerd Виссера и ответ porneL в.

 class Something { private static $foo; private static getFoo() { if ($foo === null) $foo = [[ complicated initializer ]] return $foo; } public static bar() { [[ do something with self::getFoo() ]] } } 

Но даже лучшее решение – избавиться от статических методов и использовать шаблон Singleton. Затем вы просто выполняете сложную инициализацию в конструкторе. Или сделайте его «услугой» и используйте DI, чтобы ввести его в любой класс, который ему нужен.

Вы не можете выполнять вызовы функций в этой части кода. Если вы создадите метод типа init (), который будет выполняться до того, как будет выполнен любой другой код, тогда вы сможете заполнить эту переменную.

лучший способ – создать такой способ доступа:

 /** * @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 (); откуда угодно.

В PHP 7.0.1 я смог определить это:

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

И затем используйте его так:

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

Вот, надеюсь, полезный указатель в примере кода. Обратите внимание, как функция инициализатора вызывается только один раз.

Кроме того, если вы инвертируете вызовы в StaticClass::initializeStStateArr() и $st = new StaticClass() вы получите тот же результат.

 $ 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__. "\n"; } } } print "Starting...\n"; StaticClass::initializeStStateArr(); $st = new StaticClass(); print_r (StaticClass::$stStateArr); 

Который дает :

 $ php static.php Starting... In initializeStStateArr Array ( [CA] => California [CO] => Colorado ) с $ php static.php Starting... In initializeStStateArr Array ( [CA] => California [CO] => Colorado )