स्टेटिक वैरिएबल को इनिशियलाइज़ कैसे करें


207

मेरे पास यह कोड है:

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

जो मुझे निम्नलिखित त्रुटि देता है:

पार्स त्रुटि: वाक्यविन्यास त्रुटि, अनपेक्षित '(', 'अपेक्षा') '' / 'में 19 लाइन पर / site/site/regite/registration/inc/registration.class.inc

तो, मुझे लगता है कि मैं कुछ गलत कर रहा हूं ... लेकिन अगर ऐसा नहीं है तो मैं यह कैसे कर सकता हूं? अगर मैं नियमित स्ट्रिंग्स के साथ mktime सामान को बदलता हूं, तो यह काम करता है। तो मुझे पता है कि मैं इसे इस तरह से कर सकता हूं ।

किसी के पास कुछ संकेत हैं?



2
पहला जवाब मतदान का है। देखें stackoverflow.com/a/4470002/632951
Pacerier

1
@ स्पेसर मुझे ऐसा नहीं लगता। उत्तर # 2 का उत्तर # 1
Kontrollfreak

2
@ स्पेसर 10 लोगों से पूछते हैं, उनमें से कोई भी इसे पसंद नहीं करेगा।
भैंस

जवाबों:


345

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

135
मुझे PHP बहुत पसंद है, लेकिन यह कभी-कभी बहुत अजीब होता है।
मार्को डेमायो

6
मुझे पता है कि यह पुराना है, लेकिन मैं भी इस विधि का उपयोग करता हूं। हालांकि, मैंने पाया कि कभी-कभी फू :: init () नहीं कहा जाता है। मैं कभी नीचे ट्रैक करने में सक्षम नहीं था, लेकिन सिर्फ सभी को जागरूक करना चाहता था।
लूसिफ़ेरियस

1
@porneL, पहला तरीका काम नहीं करेगा क्योंकि आपके पास निजी चरों की पहुँच नहीं है। दूसरी विधि काम करती है लेकिन यह हमें initसार्वजनिक करने के लिए मजबूर करती है जो बदसूरत है। एक बेहतर उपाय क्या है?
पचेरियर

2
@ पहला तरीका सार्वजनिक संपत्ति का एक कारण के लिए उपयोग करता है। AFAIK का इस समय PHP में कोई बेहतर उपाय नहीं है (Tjeerd Visser का जवाब हालांकि बुरा नहीं है)। क्लास लोडर में हैक को छिपाने से यह दूर नहीं जाता है, झूठी विरासत को मजबूर करता है, और यह थोड़ी चालाकी है जो अप्रत्याशित रूप से टूट सकता है (उदाहरण के लिए जब फ़ाइल की आवश्यकता होती है) (डी स्पष्ट रूप से)।
कोर्नेल

1
@porneL सरल सरणी PHP 5.6.x में मेरे लिए काम करती है, हालांकि RFC में इसका उल्लेख नहीं किया गया है। उदाहरण:class Foo {public static $bar = array(3 * 4, "b" => 7 + 8);} var_dump(Foo::$bar);
पेंग

32

यदि आपका क्लास लोडिंग पर नियंत्रण है, तो आप वहां से स्थैतिक आरंभ कर सकते हैं।

उदाहरण:

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

अपने कक्षा लोडर में, निम्नलिखित करें:

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

रिफ्लेक्शनक्लास के साथ इंटरफेस का उपयोग करने के लिए एक अधिक भारी वजन समाधान होगा:

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() }

यह कुछ हद तक c # में स्थिर कंस्ट्रक्टर्स के समान है, मैं उम्र के लिए कुछ समान उपयोग कर रहा हूं और यह बहुत अच्छा काम करता है।
क्रि।

@EmanuelLandeholm, तो विधि एक तेज़ या विधि दो तेज़ है?
पचेरियर

@ क्रिस कोई संयोग नहीं है। मैं उत्तर देने के समय c # से प्रेरित था।
इमानुएल लैंडेहोम

1
@Pacerier के पास कोई सबूत नहीं है लेकिन मुझे संदेह है कि ReflectionClass () अधिक ओवरहेड को उकसा सकता है। ओटीओएच, पहला तरीका कुछ खतरनाक धारणा बनाता है कि किसी भी वर्ग को लोडर द्वारा लोड किए गए किसी भी वर्ग में "static_init" कहा जाता है। इससे कीड़े को ट्रैक करने के लिए कुछ कठिन हो सकता है, जैसे। थर्ड पार्टी क्लासेस के साथ।
एमानुएल लैंडेहोम

23

स्थिर वैरिएबल को काम करने का तरीका खोजने के बजाय, मैं बस एक गटर फ़ंक्शन बनाना पसंद करता हूं। यदि आपको किसी विशिष्ट वर्ग से संबंधित सरणियों की आवश्यकता है, और लागू करने के लिए बहुत सरल भी उपयोगी है।

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

जहां भी आपको सूची की आवश्यकता है, बस गेट्टर विधि को कॉल करें। उदाहरण के लिए:

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

11
हालांकि यह एक सुरुचिपूर्ण समाधान है, मैं यह नहीं कहूंगा कि यह प्रदर्शन के कारणों के लिए आदर्श है, मुख्यतः क्योंकि समय की मात्रा के कारण सरणी को संभवतः आरंभ किया जा सकता है - यानी, ढेर आवंटन। चूंकि php C में लिखा गया है, मुझे लगता है कि अनुवाद एक फ़ंक्शन को कॉल करने के लिए एक एरियर को वापस करने वाले फ़ंक्शन का समाधान करेगा ... बस मेरे दो सेंट।
ज़ेयोब्लंड

इसके अलावा फ़ंक्शन कॉल PHP में महंगे हैं, इसलिए यदि वे आवश्यक नहीं हैं तो उनसे बचना सबसे अच्छा है।
मार्क रोज

14
"सबसे अच्छा जब आवश्यक न हो तो उनसे बचने के लिए" - वास्तव में नहीं। यदि वे (हो सकता है) अड़चन बन जाएं तो उनसे बचें। अन्यथा यह समयपूर्व अनुकूलन है।
मनोवैज्ञानिक ब्रम

2
@blissfreak - कोई भी वास्तविक स्थिति से बच सकता है, यदि हम कक्षा में एक स्थिर संपत्ति बनाते हैं, और getTypeList () में जांच करें कि क्या यह पहले से ही इनिशियलाइज़ हो चुका है और वापस लौटना है। यदि अभी तक इनिशियलाइज़ नहीं किया गया है, तो इसे इनिशियलाइज़ करें और उस मान को लौटाएँ।
अनुदान

12
मैं गंभीरता से फ़ंक्शन कॉल से बचने की कोशिश नहीं कर रहा हूं। कार्य संरचित प्रोग्रामिंग का आधार हैं।
अनुदान

11

मैं 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() ]]
    }
}

लेकिन इससे भी बेहतर उपाय है कि स्टैटिक तरीकों से दूर किया जाए और सिंगलटन पैटर्न का इस्तेमाल किया जाए। फिर आप बस कंस्ट्रक्टर में जटिल इनिशियलाइज़ेशन करते हैं। या इसे एक "सेवा" बनाएं और इसे किसी भी वर्ग में इंजेक्ट करने के लिए डीआई का उपयोग करें।


10

यह परिभाषा में सेट करने के लिए बहुत जटिल है। आप परिभाषा को अशक्त करने के लिए सेट कर सकते हैं, और फिर कंस्ट्रक्टर में, इसे जांचें, और अगर इसे बदला नहीं गया है - इसे सेट करें:

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

10
लेकिन क्या कंस्ट्रक्टर किसी अमूर्त वर्ग में किसी मदद के लिए होगा जो कभी त्वरित नहीं है?
शविश

एक सार वर्ग का उपयोग तब तक नहीं किया जा सकता है जब तक कि इसे पूरा और त्वरित नहीं किया जाता है। उपरोक्त सेटअप को विशेष रूप से एक कंस्ट्रक्टर में नहीं किया जाना है, जब तक कि चर का उपयोग करने से पहले इसे कहीं न कहीं कहा जाता है।
एलिस्टर बुलमैन

यह मानने के लिए एक महान विचार नहीं है कि स्थिर चर की आवश्यकता से पहले निर्माणकर्ता को बुलाया जाता है। अक्सर एक उदाहरण बनाने से पहले एक स्थिर मूल्य की आवश्यकता होती है ।
टूलमेकरसैट

4

आप कोड के इस भाग में फ़ंक्शन कॉल नहीं कर सकते। यदि आप एक init () प्रकार की विधि बनाते हैं जो किसी भी अन्य कोड से पहले निष्पादित हो जाती है तो आप तब चर को पॉप्युलेट कर पाएंगे।


init () प्रकार विधि? क्या आप एक उदाहरण दे सकते हैं? सी # में एक स्थिर निर्माता की तरह है?
शविश

@ शविश: नहीं। इसे एक नियमित स्थैतिक विधि के रूप में कक्षा परिभाषा के ठीक नीचे कहा जाना चाहिए।
व्लादिस्लाव रास्ट्रुसनी

4

PHP 7.0.1 में, मैं इसे परिभाषित करने में सक्षम था:

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

और फिर इसे इस तरह उपयोग करें:

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

FWIW: आप जो दिखाते हैं उसे PHP 7 की आवश्यकता नहीं होती है; यह उस समय ठीक काम किया गया था जब सवाल पूछा गया था: "अगर मैं नियमित स्ट्रिंग्स के साथ mktime सामान को बदलता हूं, तो यह काम करता है।" यह धागा क्या देख रहा है, एक स्टेटिक को इनिशियलाइज़ करने की तकनीक है, जब इनिशियलाइज़ेशन को एक या एक से अधिक फ़ंक्शन को कॉल करने की आवश्यकता होती है
टूलमेकर

3

सबसे अच्छा तरीका है इस तरह से एक अभिगमक बनाना है:

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

फिर आप स्थैतिक :: डीबी () कर सकते हैं; या स्वयं :: डीबी (); कहीं से भी।


-1

यहाँ एक कोड उदाहरण में एक उम्मीद के मुताबिक सहायक पॉइंटर है। ध्यान दें कि कैसे इनिशियलाइज़र फ़ंक्शन को केवल एक बार कहा जाता है।

इसके अलावा, यदि आप कॉल को उल्टा करते हैं 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
)

2
लेकिन कृपया ध्यान दें, कि आपने क्लास (ऑब्जेक्ट) का एक उदाहरण बनाया है, क्योंकि कंस्ट्रक्टर एक सार्वजनिक NONSTATIC फ़ंक्शन है। प्रश्न यह है कि क्या PHP केवल स्थिर कंस्ट्रक्टरों का समर्थन करता है (कोई उदाहरण नहीं है। उदाहरण के लिए जावा में जैसेstatic { /* some code accessing static members*/ }
मिट्जा गुस्टिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.