Как инициализировать статические переменные
У меня есть этот код:
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 с помощью регулярных строк, он будет работать. Поэтому я знаю, что я могу так поступить.
У кого-нибудь есть указатели?
Ответы
Ответ 1
PHP не может анализировать нетривиальные выражения в инициализаторах.
Я предпочитаю обойти это, добавив код сразу после определения класса:
class Foo {
static $bar;
}
Foo::$bar = array(…);
или же
class Foo {
private static $bar;
static function init()
{
self::$bar = array(…);
}
}
Foo::init();
PHP 5.6 теперь может обрабатывать некоторые выражения.
/* 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();
}
Ответ 2
Если у вас есть контроль над загрузкой классов, вы можете сделать статическую инициализацию оттуда.
Пример:
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() }
Ответ 3
Вместо того, чтобы найти способ заставить статические переменные работать, я предпочитаю просто создавать функцию 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...
}
Ответ 4
Это слишком сложно установить в определении. Вы можете установить определение в значение null, но, а затем в конструкторе, проверьте его, и если он не был изменен - установите его:
private static $dates = null;
public function __construct()
{
if (is_null(self::$dates)) { // OR if (!is_array(self::$date))
self::$dates = array( /* .... */);
}
}
Ответ 5
Я использую комбинацию Tjeerd Visser и ответа 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, чтобы ввести его в любой класс, который ему нужен.
Ответ 6
Вы не можете выполнять вызовы функций в этой части кода. Если вы создаете метод типа init(), который запускается до того, как будет выполнен любой другой код, тогда вы сможете заполнить эту переменную.
Ответ 7
Лучший способ - создать такой аксессуар:
/**
* @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(); из любого места.
Ответ 8
В PHP 7.0.1 я смог определить это:
public static $kIdsByActions = array(
MyClass1::kAction => 0,
MyClass2::kAction => 1
);
И затем используйте его следующим образом:
MyClass::$kIdsByActions[$this->mAction];
Ответ 9
Вот, надеюсь, полезный указатель в примере кода. Обратите внимание, как функция инициализатора вызывается только один раз.
Кроме того, если вы инвертируете вызовы на 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
)