2011-11-14 17 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'));