Twig instanceof for inheritance objects

时光总嘲笑我的痴心妄想 提交于 2019-12-06 17:07:37

问题


I am using the following feature from propel http://www.propelorm.org/documentation/09-inheritance.html.

I am also using Symfony2 and Twig

I have a class structure using the above feature that looks something like this

class Event {}

class Birthday extends Event {}

class Walking extends Event {}

now I pass an event object to a twig template and I want to know what type of event it is

For instance I want to display an image of a cake if its a birthday and I want to display map routes if its walking event.

I cannot use instanceof in Twig as this feature does not exist. Does anyone now why this does not exist? and is there a way I can replicate this functionality without having to do something like

 public function getType()

in each class, or

 public function isBirthday()

in the event class.

I found this on github but it is of no use to me. I have commented on their to see if I can get an answer.

https://github.com/fabpot/Twig/issues/553


回答1:


I share the opinion, that instanceof is nothing that should appear in a template. I use twig-tests for this case

class MyTwigExtension extends TwigExtension
{
    public function getTests ()
    {
        return [
            new \Twig_SimpleTest('birthday', function (Event $event) { return $event instanceof Birthday; }),
            new \Twig_SimpleTest('walking', function (Event $event) { return $event instanceof Walking; })
        ];
    }
}

And in the template

{% if event is birthday %}{# do something #}{% endif %}



回答2:


An indirect way of accomplishing this would be testing the object for a method, if you know each inherited object has a unique method. Maybe your Birthday class has a getBirthday(), while your Walking class has a getMap()?

{% if yourobject.methodName is defined %}
   //Stuff that should only output when the object in question has the requested method
{% endif %}



回答3:


Using instanceof in a template is frowned upon from an architectual standpoint. If you find yourself in a position where you "need" it, you have probably uncovered a problem in your architecture. Your getType solution in your case is probably the best. You could still put that into the event base class and read it out the name of the implementing class.




回答4:


Another solution :

class Event {
    ...
    public function isInstanceOfBirthday() {
        return $this instanceof Birthday;
    }
}

then it will works with any class that inherit from

class Birthday extends Event {}

class Walking extends Event {}

then in your twig :

{{ event.isInstanceOfBirthday ? ... something for Birthday instance ... : ... something for Walking instance ... }}

OR

{% if event.isInstanceOfBirthday %}
    ... do something for Birthday instance ...
{% else %}
    ... do something for Walking instance ...
{% endif %}



回答5:


I'm trying to make an index.html.twig that lists entities that are defined by the user, and only the fields that have been marked as 'addToListing' So I get to the point in which I don't know what I'm printing.

{% for entity in entities %}
    <tr>
        {% for heading in headings %}
            <td><a href="{{ path('document_show', { 'id': entity.id, docType: metaData.className }) }}">{{ attribute(entity, heading) }}</a></td>
        {% endfor %}
    </tr>
{% endfor %}

And heading happens to be a \DateTime :/ So for such case I'd need to | date('format') or some better solution.

Any advise on a clean solution for me?




回答6:


I had similar problem, it was related to the inheritance in Hotel software. I had a base class "RoomEquipment", and inheritance with "Bed", "ElectricAppliances"....

class BaseRoomEquipment {}

class Bed extends BaseRoomEquipment {}

class ElectricAppliances extends BaseRoomEquipment {}

And of course, a class "Room" with relation OneToMany towards RoomEquipment.

On template, I wanted to render beds only, but Room has relation to base equipment, which includes beds and electric appliances.

Instead of testing in twig template, in Room class i have created a method getBeds, and thats it.

class Room {

  private $equipment;

  public getBeds() 
  {
     $res = [];
     foreach($this->getEquipment() as $eq) {
        if ($eq instanceof Bed) $res[] = $eq;
     }
     return $res;
  }

  // Rest of class here....

}

And, of course, in Twig:

<div>
    {% for Bed in Room.beds %}
       {{ Bed.nbPersons }}
    {% endfor %}
</div>

Thanks to Property Accessor component - this is possible. Now, your twig does not have to check about instance type, nor it does no



来源:https://stackoverflow.com/questions/10113442/twig-instanceof-for-inheritance-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!