Jump to content

WireArray behavior ?


dynweb
 Share

Recommended Posts

I put the following code in my template:

$a = WireArray([
    WireArray([
        'template' => 'basic',
        'key' => 'animals',
    ]),
    WireArray([
        'template' => 'default',
        'key' => 'default',
    ]),
]);

print_r($a);

Output:

ProcessWire\WireArray Object
(
    [count] => 2
    [items] => Array
        (
            [0] => ProcessWire\WireArray Object
                (
                    [count] => 2
                    [items] => Array
                        (
                            [template] => basic
                            [key] => animals
                        )

                )

            [1] => ProcessWire\WireArray Object
                (
                    [count] => 1
                    [items] => Array
                        (
                            [template] => default
                        )
                )
        )
)

So... where is the "key" of the 2nd array element?

It only happens if the value is "default".

Any ideas ? Thank you.

 

Edit: Newest Processwire 3.0.121

Link to comment
Share on other sites

11 minutes ago, kongondo said:

I've only had a quick look at your post. It could be 'default' is a reserved word/keyword?

No, it behaves in that way when different 'keys' have the same values. One more example

$array = WireArray([
    'test' => 'test1',
    'test1' => 'test1',
    'test2' => 'test2'
]);

d($array);


count => 2
items => array (2)
  - test => "test1" (5)
  - test2 => "test2" (5)

Actually, I think that it's a bug in WireArray() function as if use new WireArray() it works as expected

$test = [
    'test' => 'test1',
    'test1' => 'test1',
    'test2' => 'test2'
];

$array = new WireArray();
$array->setArray($test);

d($array);

count => 3
items => array (3)
 - test => "test1" (5)
 - test1 => "test1" (5)
 - test2 => "test2" (5)

Here is code for WireArray();

public static function newInstance($items = null, $class = '') {
		if(empty($class)) $class = get_called_class();
		/** @var WireArray $a */
		$a = new $class();
		if($items instanceof WireArray) {
			$items->wire($a);
			$a->import($items);
		} else if(is_array($items)) {
			$a->import($items);
		} else if($items !== null) {
			$a->add($items);
		}
		return $a;
	}

So the issue is in the usage of import method as it skips any items already present in WireArray.  

  • Like 2
Link to comment
Share on other sites

6 minutes ago, kongondo said:

Ah, yes. As documented here as well:

http://processwire.com/api/ref/wire-array/import/

I think that means that existing keys will not be overwritten, cf WireArray class:

	public function import($items) {

		if(!is_array($items) && !self::iterable($items)) 
			throw new WireException('WireArray cannot import non arrays or non-iterable objects'); 

		foreach($items as $key => $value) {
			if(($k = $this->getItemKey($value)) !== null) $key = $k;
			if(isset($this->data[$key])) continue; // won't overwrite existing keys
			$this->set($key, $value); 
		}
		return $this;
	}

It seems that the line above

if(($k = $this->getItemKey($value)) !== null) $key = $k;

causes the problem.

getItemKey() uses array_search and returns the key of the first value found, so the second, identical value is missed...

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...