web-dev-qa-db-fra.com

Comment initialiser des variables statiques

J'ai ce 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
);

Ce qui me donne l'erreur suivante:

Erreur d'analyse: erreur de syntaxe, inattendu '(', expectant ')' dans /home/user/Sites/site/registration/inc/registration.class.inc à la ligne 19

Donc, je suppose que je fais quelque chose de mal ... mais comment puis-je faire cela si ce n'est pas comme ça? Si je change le contenu de mktime avec des chaînes normales, cela fonctionne. Donc je sais que je peux le faire en quelque sorte comme ça ..

Quelqu'un a des indications?

202
Svish

PHP ne peut pas analyser d'expressions non triviales dans les initialiseurs.

Je préfère contourner ce problème en ajoutant du code juste après la définition de la classe:

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

ou

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

PHP 5.6 peut gérer certaines expressions maintenant.

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

Si vous avez le contrôle sur le chargement des classes, vous pouvez effectuer une initialisation statique à partir de là.

Exemple:

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

dans votre chargeur de classe, procédez comme suit:

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

Une solution plus lourde consisterait à utiliser une interface avec ReflectionClass:

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

dans votre chargeur de classe, procédez comme suit:

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

Au lieu de trouver un moyen de faire fonctionner les variables statiques, je préfère créer simplement une fonction de lecture. Également utile si vous avez besoin de tableaux appartenant à une classe spécifique et beaucoup plus simple à implémenter.

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

Où que vous ayez besoin de la liste, appelez simplement la méthode getter. Par exemple:

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

J'utilise une combinaison des réponses de Tjeerd Visser et 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() ]]
    }
}

Mais une solution encore meilleure consiste à supprimer les méthodes statiques et à utiliser le modèle Singleton. Ensuite, vous venez de faire l'initialisation compliquée dans le constructeur. Ou faites-en un "service" et utilisez DI pour l'injecter dans n'importe quelle classe qui en a besoin.

11
Mambazo

C'est trop complexe pour être défini dans la définition. Vous pouvez toutefois définir la définition sur null, puis la vérifier dans le constructeur et, si elle n'a pas été modifiée, définissez-la:

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

Vous ne pouvez pas faire d'appels de fonction dans cette partie du code. Si vous créez une méthode de type init () qui est exécutée avant tout autre code, vous pourrez alors renseigner la variable.

4
alxp

le meilleur moyen est de créer un accesseur comme celui-ci:

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

alors vous pouvez faire static :: db (); ou self :: db (); de partout.

3
espaciomore

Dans PHP 7.0.1, j'ai pu définir ceci:

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

Et puis utilisez-le comme ceci:

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