স্ট্যাটিক ভেরিয়েবল কীভাবে শুরু করতে হয়


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

যা আমাকে নিম্নলিখিত ত্রুটি দেয়:

পার্স ত্রুটি: সিনট্যাক্স ত্রুটি, অপ্রত্যাশিত '(', প্রত্যাশা ')' in / home/user/Sites/site/regifications/inc/regifications.class.inc লাইন 19

সুতরাং, আমি অনুমান করি যে আমি কিছু ভুল করছি ... তবে যদি না হয় তবে আমি কীভাবে এটি করতে পারি? আমি যদি নিয়মিত স্ট্রিং সহ এমকেটাইম স্টাফ পরিবর্তন করি তবে এটি কাজ করে। সুতরাং আমি জানি যে আমি এটি এর মতো ধরণের করতে পারি ..

কারও কিছু পয়েন্টার আছে?



2
প্রথম উত্তরটি ভোট দেওয়া শেষ। দেখুন stackoverflow.com/a/4470002/632951
Pacerier

1
@ পেসারিয়র আমি এটি মনে করি না। উত্তর # 1 এর উত্তর # 1 এর
কনট্রলফ্রেইক

2
@ পেসারিয়ার 10 জনকে জিজ্ঞাসা করুন, তাদের মধ্যে কেউই এটি পছন্দ করবে না।
মহিষ 10

উত্তর:


345

পিএইচপি আরম্ভকারীগুলিতে অ-তুচ্ছ প্রকাশ প্রকাশ করতে পারে না।

আমি ক্লাসের সংজ্ঞা দেওয়ার পরে কোড যুক্ত করে এটিকে ঘিরে কাজ করতে পছন্দ করি:

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

অথবা

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

পিএইচপি 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
আমি পিএইচপি পছন্দ করি, তবে কখনও কখনও এটি সত্যই অদ্ভুত।
মার্কো ডেমাইও

6
আমি জানি এটি পুরানো, তবে আমিও এই পদ্ধতিটি ব্যবহার করি। তবে, আমি দেখতে পেয়েছি যে কখনও কখনও Foo :: init () বলা হয় না। আমি কখনই কেন এটি সন্ধান করতে সক্ষম হইনি, তবে কেবল সমস্ত সচেতন করতে চেয়েছিলাম।
লাভজনক

1
@ পার্নেল, প্রথম পদ্ধতিটি কাজ করবে না কারণ আপনার ব্যক্তিগত ভেরিয়েবলগুলির অ্যাক্সেস নেই। দ্বিতীয় পদ্ধতিটি কাজ করে তবে এটি আমাদেরকে initজনসাধারণে প্রচার করতে বাধ্য করে যা কুৎসিত। এর থেকে উত্তম সমাধান আর কী?
পেসারিয়ার

2
@ পেসারিয়র প্রথম পদ্ধতিটি একটি কারণে জনসাধারণের সম্পত্তি ব্যবহার করে। এএফআইএকি এই মুহুর্তে পিএইচপি-তে এর চেয়ে ভাল কোনও সমাধান নেই (তিজিরড ভিসারের উত্তর যদিও খারাপ নয়)। শ্রেণি লোডারটিতে হ্যাকটি আড়াল করে তা দূরে যায় না, মিথ্যা উত্তরাধিকারকে জোর করে, এবং এটি কিছুটা চালাকি যা অপ্রত্যাশিতভাবে ভেঙে যেতে পারে (যেমন যখন ফাইলের প্রয়োজন হয় () স্পষ্টতই)।
কর্নেল

1
@ PorneL সাধারণ অ্যারে আমার জন্য পিএইচপি 5.6.x এ কাজ করে, যদিও আরএফসিতে উল্লেখ নেই। উদাহরণ:class Foo {public static $bar = array(3 * 4, "b" => 7 + 8);} var_dump(Foo::$bar);
পাইং

32

ক্লাস লোডিংয়ের উপরে যদি আপনার নিয়ন্ত্রণ থাকে তবে আপনি সেখান থেকে স্থিতিশীল শুরু করতে পারেন do

উদাহরণ:

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

এটি সি # তে স্থির নির্মাতাদের সাথে কিছুটা বেশি সাদৃশ্যপূর্ণ, আমি বয়সের জন্য বেশ কিছু অনুরূপ ব্যবহার করছি এবং এটি দুর্দান্ত কাজ করে।
ক্রিস

ইমানুয়েলল্যান্ডহোলম, সুতরাং পদ্ধতিটি কি এক দ্রুত বা পদ্ধতি দুটি দ্রুত?
পেসারিয়ার

@ ক্রিস এটি কোনও কাকতালীয় ঘটনা নয়। উত্তর দেওয়ার সময় আমি সি # দ্বারা অনুপ্রাণিত হয়েছিলাম।
ইমানুয়েল ল্যান্ডহোম

1
@ পেসারিয়ার আমার কাছে কোনও প্রমাণ নেই তবে আমি সন্দেহ করি যে রিফ্লেকশনক্লাস () এর বেশি ওভারহেড লাগতে পারে। ওটিওএইচ, প্রথম পদ্ধতিটি কিছুটা বিপজ্জনক ধারণা অনুধাবন করে যে শ্রেণি লোডার দ্বারা লোড হওয়া কোনও শ্রেণিতে "স্ট্যাটিক_ইনাইট" নামে পরিচিত কোনও পদ্ধতি একটি স্ট্যাটিক ইনিশিয়ালাইজার। এর ফলে বাগগুলি ট্র্যাক করার জন্য কিছুটা শক্ত হতে পারে, যেমন। তৃতীয় পক্ষের ক্লাস সহ।
ইমানুয়েল ল্যান্ডহোম

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
যদিও এটি একটি মার্জিত সমাধান, তবে আমি বলব না যে এটি পারফরম্যান্সের কারণে আদর্শ, মূলত অ্যারের সম্ভাব্য পরিমাণটি শুরু হওয়ার পরিমাণের কারণে - অর্থাত, প্রচুর গাদা বরাদ্দ। যেহেতু পিএইচপি সি তে লেখা আছে, আমি কল্পনা করেছি যে অনুবাদটি কলটিতে প্রতি বিন্যাসে একটি পয়েন্টার ফিরিয়ে ফাংশনটির সমাধান করবে ... ঠিক আমার দুটি সেন্ট।
zeboidlund

অধিকন্তু ফাংশন কলগুলি পিএইচপি-তে ব্যয়বহুল, সুতরাং যদি প্রয়োজন হয় না তবে সেগুলি এড়ানো ভাল।
মার্ক রোজ

14
"প্রয়োজনীয় না হলে এগুলি এড়াতে সেরা" - সত্যই নয়। তারা (যদি) বাধা হয়ে দাঁড়ায় তবে তাদের এড়িয়ে চলুন। অন্যথায় এটি অকাল অপটিমাইজেশন।
psycho brm

2
@ ব্লিসফ্র্যাক - কেউ পুনরায় বর্ণনা করা এড়াতে পারে, যদি আমরা শ্রেণিতে একটি স্থিতিশীল সম্পত্তি তৈরি করি এবং যদি এটি ইতিমধ্যে শুরু করা হয়েছে তবে getTypeList () পরীক্ষা করে দেখুন এবং তা ফিরিয়ে দিন। যদি এখনও আরম্ভ না করা হয় তবে এটি আরম্ভ করুন এবং সেই মানটি ফিরিয়ে দিন।
গ্র্যান্টপর্কস

12
আমি গুরুত্ব সহকারে ফাংশন কল এড়ানোর চেষ্টা করব না। ফাংশনগুলি স্ট্রাকচার্ড প্রোগ্রামিংয়ের ভিত্তি।
গ্র্যান্টপর্কস

11

আমি টিজিয়ার্ড ভিজার্স এবং পর্নেলের উত্তরগুলির সংমিশ্রণটি ব্যবহার করি।

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

পিএইচপি 7.0.1 এ, আমি এটি সংজ্ঞায়িত করতে সক্ষম হয়েছি:

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

এবং তারপরে এটি ব্যবহার করুন:

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

এফডাব্লুআইডাব্লু: আপনি যা দেখান তার জন্য পিএইচপি 7 প্রয়োজন হয় না; প্রশ্নটি জিজ্ঞাসা করার সময় এটি ঠিকঠাক কাজ করেছিল : "আমি যদি নিয়মিত স্ট্রিং দ্বারা এমকিটাইম স্টাফ পরিবর্তন করি তবে এটি কার্যকর হয়।" এই থ্রেডটি যা সন্ধান করছে, তা হ'ল স্থিতির সূচনা করার কৌশল, যখন যখন প্রাথমিককরণটির প্রয়োজন হয় এক বা একাধিক ফাংশন
টুলমেকারস্টেভ

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
তবে দয়া করে নোট করুন, আপনি ক্লাসের একটি উদাহরণ তৈরি করেছেন (অবজেক্ট), কারণ কনস্ট্রাক্টর একটি পাবলিক ননস্ট্যাটিক ফাংশন। প্রশ্নটি হল: পিএইচপি কি কেবল স্থিতিশীল কন্সট্রাক্টরকে সমর্থন করে (কোনও উদাহরণ তৈরি করে না example উদাহরণস্বরূপ জাভাstatic { /* some code accessing static members*/ }
মিতজা গুস্টিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.