2014-02-26 70 views
0

我正在寫一個class(散列),它增加了數組的行爲。實例化的對象應該可以與基本數組互換,所以我可以將它傳遞給需要數組的方法。 另外我希望能夠將對象投射到陣列PHP:使對象行爲像陣列

它應該通過的測試是here

我以爲實現ArrayAccess就足夠了,但事實並非如此。

或者可能實施了__toArray()方法,如toString()用於投射字符串,但它也不起作用。

編輯:

$hash = new Hash(array(
    'foo' => 'bar', 
    'bar' => 'barfoo', 
)); 

function echoArray(array $array) { 
    print_r($array); 
} 

echoArray($hash); 
// Catchable fatal error: Argument 1 passed to echoArray() 
// must be of the type array, object given 

print_r((array) $hash); 
/* 
Array 
(
    [*_values] => Array 
     (
      [foo] => bar 
      [bar] => barfoo 
     ) 
) 
*/ 

是否有實現這一行爲的一種方式?

預先感謝您。

+9

聽起來像一個偉大的想法。 ..這裏有個問題嗎? – blockhead

+0

這不是關於原始帖子,而是注意到你在Hash.php中使用get_called_class():164。如果你想避免它,你可以嘗試刪除它並使用「新的靜態($ params);」在Hash.php上:165。 –

+0

@NikoHujanen取決於他必須支持哪個版本的PHP(關於get_called_class() - 上面的帖子)。 – frodeborli

回答

0

很遺憾,很多內部函數都不可能要求原始數組使用你的對象。是的,用戶定義的PHP函數可以使用它作爲一個數組(儘管不是,如果你需要一個參數是一個基本數組),但這樣的東西array_map ...不會:

<?php 
class obj implements arrayaccess { 
    private $container = array(); 
    public function __construct() { 
     $this->container = array(
      "one" => 1, 
      "two" => 2, 
      "three" => 3, 
     ); 
    } 
    public function offsetSet($offset, $value) { 
     if (is_null($offset)) { 
      $this->container[] = $value; 
     } else { 
      $this->container[$offset] = $value; 
     } 
    } 
    public function offsetExists($offset) { 
     return isset($this->container[$offset]); 
    } 
    public function offsetUnset($offset) { 
     unset($this->container[$offset]); 
    } 
    public function offsetGet($offset) { 
     return isset($this->container[$offset]) ? $this->container[$offset] : null; 
    } 
} 

$obj = new obj; 

function requirearray(array $obj){}; 

requirearray($obj); 
// Catchable fatal error: Argument 1 passed to requirearray() must be of the type array, object given... 

var_dump(array_map('strlen',$obj)); 
// Warning: array_map(): Argument #2 should be an array 
// NULL 
2

引述你的描述:

實現了ArrayAccess就足以

這裏的文檔:PHP ArrayAcces interface

我不認爲有什麼多說了。我最終可以添加一個示例:

class SomeClassImplementingArrayAccess implements arrayaccess { 
    // implements all required methods 
} 

$arrayAccessObj = new SomeClassImplementingArrayAccess(); 
$arrayAccessObj['abc'] = 'def'; //it calls the `SomeClassImplementingArrayAccess::offsetSet` method 
$objValueABC = $arrayAccessObj['abc']; //it calls the `SomeClassImplementingArrayAccess::offsetGet` method 
+0

謝謝@matewka。但事實是,實施ArrayAccess是不夠的。還有其他事情必須完成。 – Marcelo

0

PHP在ArrayAccess接口中沒有toArray()方法。我認爲這種說法會成功:

$hash = new Hash($array); 
$this->assertEqual($array, $hash->toArray()); 

PHPUnit的測試將不會成功,因爲在與所述對象的屬性的數組投對象的數組結果。

但是,該對象應該以當前形式的數組工作。在你的offsetGet-implementation中,你應該檢查你是否返回一個數組。在這種情況下,我會將結果包裝在一個新的Hash對象中。如果注意引用(使用&操作符),更改將傳播到父哈希。

即:

目前

$array["somekey"][] = "Something"; 

的工作,但

$object["somekey"][] = "Something"; 

將失敗。

你也可以發現變化中的 「子哈希」,並保持到父散列的引用 - 和替換父:

在offsetSet:

if($this->parent) $this->parent->values[$this->keyInParent] = $this->values; 

在offsetGet:

if(is_array($this->values[$key])) { 
    $hash = new Hash($this->values[$key]); 
    $hash->parent = $this; 
    $hash->keyInParent = $key; 
    return $hash; 
} 
+0

我喜歡你的偏移獲取建議,但我寧願檢查offsetSet實現中的數組。我會開一個關於這個問題的問題,所以我不會忘記它。 TKS! – Marcelo

+0

@Marcelo然後你還必須在構造函數中遍歷整個數組,我認爲這會非常低效。 – frodeborli

+0

是的,這是正確的。 =/ – Marcelo