InstanceOf operator in Fluid

Hi,

we have different users (different domain models), and I have to tell them apart in the templates.

It would be fine to have something like the instanceOf operator in Fluid.
I don’t found a solution, so I added the property “userType” to the models as a work around.
It works fine- but I don’t like.

Any hints?

Klaus

Again, just create a custom ViewHelper (look at some existing ones extending the AbstractConditionViewHelper).

But having something like

<x:ifInstanceOf object="{model}" interface="Some\Interface">
  <f:then>
    ...
  </f:then>
<x:ifInstanceOf

Within your Fluid Template… That’s almost definitely better put into a lower level. The View should not care about implementation details.

If you explain your higher level requirements we can maybe come up with a cleaner solution

I would just like to suggest something a bit different. IMHO rather implement a x:instanceOf ViewHelper that returns a boolean and use the “normal” f:if ViewHelper instead of implementing a custom ifInstanceOf. I would discourage that in general.

Hi Christian,

sounds more universal to me.
This gives me a new Idea:
I will try out a x:format.classname ViewHelper, whitch accepts an object and delivers the class name.

Kind of instanceOf:

<f:if condition="{objectInQuestion -> x:format.classname()} == 'ClassNameToTest'">

Mostly we will use it inside of switch statements. With this ViewHelper we can switch classnames:

<f:switch expression="{objectInQuestion -> x:format.classname()}">
    <f:case value="ClassNameToTest">

What do you think of that one?

Klaus

Sounds like too much logic in templates to me.

Also instead of switch I would rather use partials and dynamically decide the partial name based on class or raher some type property in the class(es).

Thanks Christian.

I will stick with my type property.

Could you please elaborate why you discourage that?
IMO

<x:ifInstanceOf object="{model}" interface="Some\Interface">
    display something
</x:ifInstanceOf>

is much easier to comprehend than

<f:if condition="{model -> x:ifInstanceOf(interface: 'Some\Interface')}">
    display something
</f:if>

Besides I think that using a ViewHelper that doesn’t actually render a string already suggests that it does some logic that should be moved somewhere else.

Speaking of which: @energyWinner can you describe your high-level requirements a little bit?
I’m sure you can solve this much easier and more flexible with polymorphism

First of all:

This is kind of a luxury problem. I just want to make it better.
Here is my solution so far:

An extract from index.html:

        <f:for each="{members}" as="member">
            <f:switch expression="{member.memberType}">
                <f:case value="AdultMember">
                   <neos:link.module path="cooperative/members/adultMembers"  action="edit" arguments="{member: member}">
                </f:case>

                <f:case value="MinorMember">
                </f:case>

                <f:case value="CorporateMember">
                </f:case>
                <f:defaultCase>
                    UNBEKANNTER TYP
                </f:defaultCase>
            </f:switch>
        </f:for>

I use class table inheritance:

Parent : Member
Children AdultMember, MinorMember, CorporateMember
They all use different ModuleControllers.

Sure, I actually have two arguments that I feel make this the better best practice choice:

  1. It’s way more flexible. See below, if at some point you notice a if/else doesn’t cut it you can just reuse the VH in a case, no problem there.

  2. easier/performance. Writing a condition VH (and especially a fast condition ViewHelper) is not easy. I took quite some time optimising the existing if VH. Writing an simple bool providing VH is easy and can also be optimised quickly. So I prefer people doing that and benefitting from the optimised if VH automatically.
    It’s for me more in line with thinking in simple helpers strung together to do something complicated instead of doing it all in one big tihng.