2011-11-14 18 views
0

我有使用words.separated.by.dots鍵保存數據存儲/數據訪問類,它成爲如下:PHP的算法 - 如何實現,如果沒有EVAL

$object = new MyArray() 
    $object->setParam('user.name','marcelo'); 
    $object->setParam('user.email','[email protected]'); 

    $object->getParams(); 

    /* 
    array(
     'user' => array(
      'name' => 'marcelo', 
      'email' => '[email protected]' 
     ) 
    ); 
    */ 

據工作,但unsetParam()方法實施起來非常可怕。發生這種情況是因爲我不知道如何在沒有eval()函數的情況下實現這個功能。雖然它在工作,但我發現它是一個非常具有挑戰性的算法,並且您可能會發現試圖在沒有eval()的情況下實現這一點。

class MyArray { 
    /** 
    * @param string $key 
    * @return Mura_Session_Abstract 
    */ 
    public function unsetParam($key) 
    { 
     $params = $this->getParams(); 
     $tmp = $params; 
     $keys = explode('.', $key); 

     foreach ($keys as $key) { 
      if (!isset($tmp[$key])) { 
       return $this; 
      } 
      $tmp = $tmp[$key]; 
     } 

     // bad code! 
     $eval = "unset(\$params['" . implode("']['", $keys) . "']);"; 
     eval($eval); 

     $this->setParams($params); 
     return $this; 
    } 
} 

測試方法:

public function testCanUnsetNestedParam() 
{ 
    $params = array(
     '1' => array(
      '1' => array(
       '1' => array(
        '1' => 'one', 
        '2' => 'two', 
        '3' => 'three', 
       ), 
       '2' => array(
        '1' => 'one', 
        '2' => 'two', 
        '3' => 'three', 
       ), 
      ) 
     ), 
     '2' => 'something' 
    ); 

    $session = $this->newSession(); 
    $session->setParams($params); 

    unset($params['1']['1']['1']); 
    $session->unsetParam('1.1.1'); 

    $this->assertEquals($params, $session->getParams()); 
    $this->assertEquals($params['1']['1']['2'], $session->getParam('1.1.2')); 
} 

回答

1

是這個嗎?

<?php 
$params = array(
    '1' => array(
     '1' => array(
     '1' => array(
      '1' => 'one', 
      '2' => 'two', 
      '3' => 'three', 
     ), 
     '2' => array(
      '1' => 'one', 
      '2' => 'two', 
      '3' => 'three', 
     ), 
     ) 
    ), 
    '2' => 'something' 
    ); 

function unsetParam(&$array, $paramString) { 
$cur =& $array; 
$splitted = explode(".", $paramString); 
$len = count($splitted) - 1; 

    for($i = 0; $i < $len; ++$i) { 

     if(isset($cur[ $splitted[ $i ] ])) { 
     $cur =& $cur[ $splitted[ $i ] ]; 
     } 
     else { 
     return false; 
     } 


    } 

unset($cur[ $splitted[$i] ]); 


} 

unsetParam($params, "1.1.1"); 

print_r($params); 

/* 
Array 
(
    [1] => Array 
    (
     [1] => Array 
     (
      [2] => Array 
      (
       [1] => one 
       [2] => two 
       [3] => three 
      ) 

     ) 

    ) 

    [2] => something 
) 
*/ 
+0

創意使用參考:) – Kato

+0

非常好!非常感謝你! – Marcelo

1

你可以使你的代碼更容易,如果你只在你getParams方法被劃分爲多維數組:

class MyArray { 
    private $params = array(); 

    public function setParam($key, $value) { 
     $this->params[$key] = $value; 
    } 
    /** 
    * @param string $key 
    * @return Mura_Session_Abstract 
    */ 
    public function unsetParam($key) 
    { 
     unset($this->params[$key]); 
     return $this; 
    } 

    public function getParams() { 
     $retval = array(); 
     foreach ($this->params as $key => $value) { 
      $aux = &$retval; 
      foreach (explode(".", $key) as $subkey) { 
       if (!isset($aux[$subkey])) $aux[$subkey] = array(); 
       $aux = &$aux[$subkey]; 
      } 
      $aux = $value; 
     } 
     return $retval; 
    } 
} 
+0

這是迄今爲止最好的答案,imho;密鑰是唯一的,爲什麼多維數組甚至有用?只要存儲/檢索使用string.with.dots,除非有一些令人信服的細節,我們還沒有聽說過? – Kato

+0

多維陣列更符合我的需求。我的課很像以上,最後我改變了。 – Marcelo

+0

@加藤,讓我們把你的論點提到它的邏輯結論:爲什麼這整個班級甚至需要? :D – Esailija

0

@gustavotkg和@Esailija都已經提供了一些偉大的想法。這是另一個簡單,易於理解和簡短的方法,它可以避免unset()(在某些情況下可以獲得quirky)。

這,當然,是在$ PARAMS最有用的是限制在小於,也就是說,值1K-10K(它開始變得有點在CPU /內存部門昂貴):

<?php 

$params = array(
    '1' => array(
     '1' => array(
     '1' => array(
      '1' => 'one-one', 
      '2' => 'one-two', 
      '3' => 'one-three', 
     ), 
     '2' => array(
      '1' => 'two-one', 
      '2' => 'two-two', 
      '3' => 'two-three', 
     ), 
    ) 
    ), 
    '2' => 'something' 
); 

function filterParams($params, $refKey, $base = '') { 
    $newvals = array(); 
    foreach($params as $k=>$v) { 
     $joinedKey = $base? $base . '.' . $k : $k; 
     if($joinedKey != $refKey) { 
     $newvals[$k] = is_array($v)? filterParams($v, $refKey, $joinedKey) : $v; 
     } 
    } 
    return $newvals; 
} 

var_dump(filterParams($params, '1.1.2'));