phpcr-odm icon indicating copy to clipboard operation
phpcr-odm copied to clipboard

Support nested associative arrays

Open dantleech opened this issue 11 years ago • 46 comments

It should be possible to have an array type which automatically creates a structure, e.g

class Site {
    /**
     * @PHPCR\AssocArray()
     */
     protected $preferences;
}

Then automatically map that to a PHPCR structure:

/site
    preferences/
         - jcr:primaryType  = phpcr:associative_array
         - key1 = value 
         key2/
             - key3: = value
             - key4: = value
             key5/

dantleech avatar Feb 10 '14 16:02 dantleech

can php array keys be anything else than strings? if not, that should actually be doable. i think we would need to find a better name, as we already have multivalue with assoc=true which is used for flat key-value hashmaps. something like NestedArray?

but anyways, lets not start this before the cmf 1.1 is released.

dbu avatar Feb 10 '14 17:02 dbu

php array keys can be integers and strings, nothing else

lsmith77 avatar Feb 11 '14 03:02 lsmith77

I would suggest an handling equal to the type setting in the JMSSerialzerBundle. It should be important to keep strings for the key to set them as localnames by default.

If the phpcr-odm can handle this type setting it should be possible to persist complete document-structures in an equal way We serialize objects to XML for example. The only difference should be: the structures have to contain Nodes as Wrapper for other properties.

I think this is a little bit more than the issue started, but goes in the same way. Cause if We start to add deeper array there can be a way of setting deeper documents instead of reference them as children. This can be a Second way.

ElectricMaxxx avatar Feb 11 '14 06:02 ElectricMaxxx

Oh i wrote nonesense. But can not delete it at the momentfrom my mobile phone.

Thought he wants to set the deeper arrays as real child documents.

ElectricMaxxx avatar Feb 11 '14 06:02 ElectricMaxxx

On which level would this feature be implemented? Only in the ODM, or would this already be placed in the PHPCR-Specification?

danrot avatar Feb 11 '14 07:02 danrot

Only odm, the phpcr spec is linked to jcr. And its not a basic thing, its just syntactic sugar to automatically store data without objects.

----- Reply message ----- Von: "Daniel Rotter" [email protected] An: "doctrine/phpcr-odm" [email protected] Cc: "David Buchmann" [email protected] Betreff: [phpcr-odm] Support nested associative arrays (#417) Datum: Di., Feb. 11, 2014 08:05 On which level would this feature be implemented? Only in the ODM, or would this already be placed in the PHPCR-Specification?

— Reply to this email directly or view it on GitHub.

dbu avatar Feb 11 '14 07:02 dbu

Could we not do this as a BC break? As it would otherwise overlap with the functionality of assoc=true

dantleech avatar Feb 11 '14 15:02 dantleech

we could add another thing like assoc, calling it nested and then it would persist differently, but its still an attribute field and not a children mapping in phpcr-odm terms.

dbu avatar Feb 11 '14 15:02 dbu

Not sure mapping it as an attribute field would make sense .. i.e. @Integer(nested=true), @String(nested=true). Would we then cast all the elements as integer or string depending on the field type?

I think a dedicated field type would make more sense, (like Doctrines @Field(type=phparray))

We could then either unconditionally map all the property values as string or dynamically cast them.

dantleech avatar Feb 11 '14 15:02 dantleech

yeah you are right, a field like @Array resp @Field(type=array) sounds good. afaik we call the other thing multivalue, and multivalue is just that, while array maps to phpcr nodes.

dbu avatar Feb 11 '14 16:02 dbu

Is it possible to get an @Field(type=<integer,string>) to get valdation on keys and values for their types? Sounds cool for Annotation, but imposible for xml config. By this it should be easy to go one Level deeper and so on.

ElectricMaxxx avatar Feb 11 '14 17:02 ElectricMaxxx

Oh my signs are gone. Ment @Field(type=<integer,string>)

ElectricMaxxx avatar Feb 11 '14 17:02 ElectricMaxxx

if we don't specify it, the types will be autodetermined by phpcr and come back in the right type on loading (string / integer / float / boolean)

dbu avatar Feb 14 '14 08:02 dbu

Recently I had some issues with that when there were null values in an array (using assoc=true) forcing me to remove all null velues before persisting.

uwej711 avatar Feb 14 '14 10:02 uwej711

uh, i think indeed in phpcr setting something to null means removing it. so your problem was that the keys get shifted because values disapear when reloading the property? maybe we should fix persisting assoc arrays to clean null values before storing the keys and values. otherwise we would need to store the indexes that where null in a 3rd field and on restoring the array put them back in the right places. that sounds tricky, but would probably the least wtf. do you want to open a separate issue for this? can we address this in like the next couple of days to get it into the 1.1 release? there is potential BC break here, if people somehow worked around the bogus behaviour.

dbu avatar Feb 14 '14 10:02 dbu

Does JCR store property type in the property (i.e. so something that is dropped in PHPCR) or is it the responsability of the nodeType definition?

Having metadata on the properties sounds awkward indeed.

dantleech avatar Feb 14 '14 10:02 dantleech

@dantleech the type of a property is stored in the property itself (the type is just there to enforce what type a property may have). i think uwe was talking about something different - null values are simply not stored in phpcr. assuming the 'test' property exists, $node->setPropertyValue('test', null) is the same as $node->getProperty('test')->remove() . this seems to hold true for arrays as well (though only in jackalope-jackrabbit probably.)

dbu avatar Feb 14 '14 11:02 dbu

@dbu so the type is stored with the property? Looking at a PHPCR dump I don't see any data other than the value on the property, I thought it was dynamically inferred.

If the type is stored with the property, can we not add a custom type for null?

dantleech avatar Feb 14 '14 11:02 dantleech

@dantleech look at an export in the system view, you will see the type. the types of properties are a limited set, there are no custom types and there is no type for null - the doc is quite explicit on the semantics of null: http://www.day.com/specs/jcr/2.0/10_Writing.html#10.4.2.4%20No%20Null%20Values

dbu avatar Feb 14 '14 11:02 dbu

@dbu: I can't remember from heart but I think Jackalope or phpcr-utils throw an exception somewhere when you try to store an array with assoc=true and null values.

uwej711 avatar Feb 14 '14 12:02 uwej711

i can't store null values. what i get is

[PHPCR\ValueFormatException]
Can not determine type of property with value "NULL"

not an extremly helpful message, but at least it does not work to create messed up data.

dbu avatar Feb 21 '14 13:02 dbu

Shall we do this for 1.1? I might be able to look at it at the weekend if nobody else is interested.

dantleech avatar Feb 21 '14 13:02 dantleech

you mean the validation? that would be nice. for the original topic of nested associative arrays, i am -1 as this is a totally new thing with quite some effort involved, and we really need to get 1.1 out and the cmf bundles 1.1 out. we are behind the roadmap by almost 2 months...

dbu avatar Feb 21 '14 14:02 dbu

This would also need some special handling for null values in the array, as properties with null values are not stored by phpcr, so you will loose the keys!

uwej711 avatar Mar 19 '14 13:03 uwej711

see #457 for how uwe solved this for the hashmaps case - the solution here would probably look similar.

dbu avatar Mar 19 '14 14:03 dbu

Hmm. Just had a look at this and one issue is how or if we should handle translations here?

dantleech avatar Oct 26 '14 16:10 dantleech

i would handle them for the whole property, as with non-nested arrays. if the property is translated, the whole thing is translated. if you use children translation strategy, there is no problem. for attribute strategy, if the idea is to create subnodes, we should use the same naming schema as for properties for the top level node of the structure.

dbu avatar Oct 27 '14 07:10 dbu

ok, i thought the same but it struck me as being maybe non-trivial - would this open a box of refactorings do you think?

dantleech avatar Oct 27 '14 07:10 dantleech

maybe the assumptions of the parameter to a translation strategy needs to be altered a bit - maybe not even that, not sure. apart from that i expect it to be rather straightforward.

dbu avatar Oct 27 '14 08:10 dbu

I just wrote a an event listener class for SuluCMF which does this. It uses a dot-delimited property name to store multi-dimensional arrays.

Name Type Vaue
foo.bar.bar STRING Value 1
foo.boo.baz LONG 1234
foo.car STRING Value 2

Would give

array(
    'foo' => array(
        'bar' => => array(
            'bar' => 'Value 1',
            'baz' => 1234,
        ),
        'car' => 'Value 2',
    ),

Will try and port it here.

dantleech avatar Jan 10 '15 17:01 dantleech