2011-08-26 18 views
6

मुझे अपने आवेदन में Config कक्षा मिली है, जो स्थिर कॉन्फ़िगरेशन सेटिंग्स लोड करता है और उन्हें सरणी में पार्स करता है।
जैसा कि मुझे रनटाइम के दौरान कुछ तत्वों को ओवरराइड करने की आवश्यकता है, मुझे इसे करने से Config -class के अंदर सार्वजनिक चर का उपयोग करना होगा; $config->values['onelevel']['twolevel'] = 'changed';PHP: बहुआयामी सरणी को संशोधित करने का सबसे साफ तरीका?

मैं एक विधि है कि override कि मेरे लिए यह करता है कहा जाता है बनाने के लिए चाहते हैं, लेकिन मैं क्या यह करने के लिए सबसे अच्छा तरीका है चारों ओर मेरे सिर प्राप्त नहीं कर सकते के रूप में मेरे config फाइल में मौजूद स्तरों के अज्ञात राशि प्राप्त कर सकते हैं भविष्य।

$config->onelevel->twolevel = 'changed' जैसे कुछ करना अच्छा लगेगा और __set जादू विधि घोंसले का ख्याल रखेगी, लेकिन जो मैं कह सकता हूं, उससे संभव नहीं है।

ऐसा करने का सबसे अच्छा तरीका क्या होगा?

+0

शायद डेटा उस तरह का शब्द "config" में नहीं जा सकता है; इसे डीबी – Dor

+0

में स्टोर करें, जब आप मेरे प्रश्न की आवश्यकताओं को अधिक निकटता से पूरा करते हैं तो आपने एरिकपेरिक के उत्तर को सबसे अच्छे जवाब के रूप में क्यों चुना? ऐसा नहीं है कि मैं एरिकपेरिक प्रतिनिधि अंक देना नहीं चाहता हूं। मैं सिर्फ उत्सुक हूं कि आपको क्यों लगा कि उसका जवाब बेहतर जवाब था? –

+0

मैंने मूल रूप से सोचा था कि जब तक मैंने आपके अपडेट किए गए संस्करण को नहीं देखा तब तक उनका समाधान काफी साफ था। 'ArrayObject' का उपयोग करना कुछ ऐसा है जो मैंने पहले कभी नहीं किया है, निश्चित रूप से इसे देखने की ज़रूरत है! – Industrial

उत्तर

6

यह तुम क्या चाहते करने के लिए संभव है:

यह एक ओवरराइड समारोह Demo का एक कोड उदाहरण है।

यह उदाहरण काफी हद तक Zend_Config से प्रेरित है और ArrayAccess interface पर PHP दस्तावेज़ों में दिया गया उदाहरण है।

संपादित करें:
एक नाबालिग चेतावनी के साथ : आप के रूप में वर्ग आंतरिक रूप से खुद का एक उदाहरण के लिए सरणी डेटा गुप्त की जरूरत है एक सरणी का प्रतिनिधित्व है, यह एक सरणी में बदलने के लिए डेटा पर toArray() कॉल करने के लिए, की जरूरत है ऑब्जेक्ट प्रॉपर्टी ऑपरेटर ->:

एह, यह वास्तव में अब आवश्यक नहीं है, क्योंकि यह अब ArrayAccess लागू करता है।;-)
/संपादन

class Config 
    implements ArrayAccess 
{ 
    protected $_data; 

    public function __construct(array $data) 
    { 
     foreach($data as $key => $value) 
     { 
      $this->$key = $value; 
     } 
    } 

    public function __get($key) 
    { 
     return $this->offsetGet($key); 
    } 

    public function __isset($key) 
    { 
     return $this->offsetExists($key); 
    } 

    public function __set($key, $value) 
    { 
     $this->offsetSet($key, $value); 
    } 

    public function __unset($key) 
    { 
     $this->offsetUnset($key); 
    } 

    public function offsetSet($offset, $value) 
    { 
     $value = is_array($value) ? new self($value) : $value; 

     if(is_null($offset)) 
     { 
      $this->_data[] = $value; 
     } 
     else 
     { 
      $this->_data[ $offset ] = $value; 
     } 
    } 

    public function offsetExists($offset) 
    { 
     return isset($this->_data[ $offset ]); 
    } 

    public function offsetUnset($offset) 
    { 
     unset($this->_data[ $offset ]); 
    } 

    public function offsetGet($offset) 
    { 
     return isset($this->_data[ $offset ]) ? $this->_data[ $offset ] : null; 
    } 

    public function toArray() 
    { 
     $array = array(); 
     $data = $this->_data; 
     foreach($data as $key => $value) 
     { 
      if($value instanceof Config) 
      { 
       $array[ $key ] = $value->toArray(); 
      } 
      else 
      { 
       $array[ $key ] = $value; 
      } 
     } 
     return $array; 
    } 
} 

संपादित 2:
Config वर्ग भी बहुत ArrayObject का विस्तार करके सरल किया जा सकता। एक अतिरिक्त लाभ के रूप में, आप इसे एक उचित सरणी में भी डाल सकते हैं।

class Config 
    extends ArrayObject 
{ 
    protected $_data; 

    public function __construct(array $data) 
    { 
     parent::__construct(array(), self::ARRAY_AS_PROPS); 
     foreach($data as $key => $value) 
     { 
      $this->$key = $value; 
     } 
    } 

    public function offsetSet($offset, $value) 
    { 
     $value = is_array($value) ? new self($value) : $value; 

     return parent::offsetSet($offset, $value); 
    } 
} 

उदाहरण उपयोग:

$configData = array(
    'some' => array(
     'deeply' => array(
      'nested' => array(
       'array' => array(
        'some', 
        'data', 
        'here' 
       ) 
      ) 
     ) 
    ) 
); 
$config = new Config($configData); 
// casting to real array 
var_dump((array) $config->some->deeply->nested->array); 

$config->some->deeply->nested->array = array('new', 'awsome', 'data', 'here'); 
// Config object, but still accessible as array 
var_dump($config->some->deeply->nested->array[ 0 ]); 

$config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ] = array('yet', 'more', 'new', 'awsome', 'data', 'here'); 
var_dump($config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ]); 

$config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ][] = 'append data'; 
var_dump($config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ]); 

var_dump(isset($config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ])); 

unset($config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ]); 
var_dump(isset($config[ 'some' ][ 'deeply' ][ 'nested' ][ 'array' ])); 

// etc... 
+0

हाय fireeyedboy। कृपया यहां एक नज़र डालें और देखें कि क्या आपको कोई विचार है या नहीं; http://stackoverflow.com/questions/7254675/extending-arrayobject-in-php-properly – Industrial

+0

@ इंडस्ट्रील: संयोग से, मैं सिर्फ सवाल देख रहा था। :) –

0

मैं तर्कों को अनिश्चित राशि के साथ एक फ़ंक्शन कर दूंगा, और वहां से तर्क प्राप्त करने के लिए func_get_args() का उपयोग कर सकता हूं, यह बस अपडेट हो रहा है।

0

कुछ समय पहले मैं एक समारोह है कि मुझे स्ट्रिंग पथ के माध्यम से एक सरणी तक पहुंचने देने की आवश्यकता थी, हो सकता है आपको लगता है कि का उपयोग कर सकते हैं:

function PMA_array_write($path, &$array, $value) 
{ 
    $keys = explode('/', $path); 
    $last_key = array_pop($keys); 
    $a =& $array; 
    foreach ($keys as $key) { 
     if (! isset($a[$key])) { 
      $a[$key] = array(); 
     } 
     $a =& $a[$key]; 
    } 
    $a[$last_key] = $value; 
} 

उदाहरण: PMA_array_write('onelevel/twolevel', $array, 'value');

+0

ओह, धन्यवाद। निश्चित – Crack

0

ठीक है, आप ने कहा आप पार्स उन्हें सरणी में। उन्हें stdObjects में क्यों न पाएं और फिर बस $config->onelevel->twolevel = 'changed' करें जैसा आप चाहते हैं? :)

5

मुझे भी यह समस्या है, और मैंने इसे इस कोड से हल किया है। हालांकि यह एपीआई पर आधारित था जैसे: Config::set('paths.command.default.foo.bar')

<?php 

$name = 'paths.commands.default'; 
$namespaces = explode('.', $name); 

$current = &$this->data; // $this->data is your config-array 
foreach ($namespaces as $space) 
{ 
    $current = &$current[$space]; 
} 
$current = $value; 

यह केवल सरणी के माध्यम से लूपिंग और संदर्भ चर के साथ वर्तमान मान का ट्रैक पकड़ रहा है।

0

आप या तो अपने आप को एक प्रकार का निर्माण कर सकते हैं, जो आप जिस इंटरफ़ेस को ढूंढ रहे हैं उसे प्रदान कर रहे हैं या आप जिस सहायक कार्य का वर्णन करते हैं उसके साथ जाते हैं।

$array = array(
    'a' => array('b' => array('c' => 'value')), 
    'b' => array('a' => 'value'), 
); 

function override($array, $value) { 
    $args = func_get_args(); 
    $array = array_shift($args); 
    $value = array_shift($args); 
    $set = &$array; 
    while(count($args)) 
    { 
     $key = array_shift($args); 
     $set = &$set[$key]; 
    } 
    $set = $value; 
    unset($set); 
    return $array; 
} 

var_dump(override($array, 'new', 'a', 'b', 'c')); 
संबंधित मुद्दे