Svish
Svish

Reputation: 158351

How to initialize static variables

I have this code:

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

Which gives me the following error:

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

So, I guess I am doing something wrong... but how can I do this if not like that? If I change the mktime stuff with regular strings, it works. So I know that I can do it sort of like that..

Anyone have some pointers?

Upvotes: 221

Views: 225819

Answers (10)

Mambazo
Mambazo

Reputation: 175

I use a combination of Tjeerd Visser's and porneL's answer.

class Something
{
    private static $foo;

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

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

But an even better solution is to do away with the static methods and use the Singleton pattern. Then you just do the complicated initialization in the constructor. Or make it a "service" and use dependency injection to inject it into any class that needs it.

Upvotes: 13

David Spector
David Spector

Reputation: 1677

In my case, I'm using both static and nonstatic class properties, and I might even have main program code referencing the static part of the class before defining the class. Since static portions of classes don't have constructors, just add a manual constructor to initialize any variables requiring nontrivial calculation:

class A
   {
   static $a; // Initialized by Init()
   static function Init()
      {
      A::$a=nontrivial();
      {
   }
...
A::Init();    // Initialize static part of class
...
$obj=new A(); // Using initialized class as an object

Upvotes: 0

Kornel
Kornel

Reputation: 100220

PHP can't parse non-trivial expressions in initializers.

I prefer to work around this by adding code right after definition of the class:

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

or

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

PHP 5.6 can handle some expressions now.

/* 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();
}

Upvotes: 360

Buffalo
Buffalo

Reputation: 4052

In PHP 7.0.1, I was able to define this:

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

And then use it like this:

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

Upvotes: 4

espaciomore
espaciomore

Reputation: 348

best way is to create an accessor like this:

/**
* @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;
}

then you can do static::db(); or self::db(); from anywhere.

Upvotes: 4

David Luhman
David Luhman

Reputation: 129

Here is a hopefully helpful pointer, in a code example. Note how the initializer function is only called once.

Also, if you invert the calls to StaticClass::initializeStStateArr() and $st = new StaticClass() you'll get the same result.

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

Which yields :

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

Upvotes: -1

diggie
diggie

Reputation: 465

Instead of finding a way to get static variables working, I prefer to simply create a getter function. Also helpful if you need arrays belonging to a specific class, and a lot simpler to implement.

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

Wherever you need the list, simply call the getter method. For example:

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

Upvotes: 24

Emanuel Landeholm
Emanuel Landeholm

Reputation: 1408

If you have control over class loading, you can do static initializing from there.

Example:

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

in your class loader, do the following:

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

A more heavy weight solution would be to use an interface with ReflectionClass:

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

in your class loader, do the following:

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

Upvotes: 34

Alister Bulman
Alister Bulman

Reputation: 35167

That's too complex to set in the definition. You can set the definition to null though, and then in the constructor, check it, and if it has not been changed - set it:

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

Upvotes: 10

alxp
alxp

Reputation: 6341

You can't make function calls in this part of the code. If you make an init() type method that gets executed before any other code does then you will be able to populate the variable then.

Upvotes: 3

Related Questions