Twig instanceof для объектов наследования

Я использую следующую функцию от propel http://www.propelorm.org/documentation/09-inheritance.html.

Я также использую Symfony2 и Twig

У меня есть структура класса, использующая вышеприведенную функцию, которая выглядит примерно так:

class Event {}

class Birthday extends Event {}

class Walking extends Event {}

теперь я передаю объект события в шаблон ветки, и я хочу знать, какой тип события он

Например, я хочу отображать изображение торта, если его день рождения, и я хочу отображать маршруты карты, если это событие для ходьбы.

Я не могу использовать instanceof в Twig, поскольку эта функция не существует. Кто-нибудь теперь, почему этого не существует? и есть ли способ реплицировать эту функциональность, не делая что-то вроде

 public function getType()

в каждом классе, или

 public function isBirthday()

в классе событий.

Я нашел это на github, но это бесполезно для меня. Я прокомментировал их, чтобы узнать, могу ли я получить ответ.

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

Ответы

Ответ 1

Я разделяю мнение, что instanceof ничего не должно появляться в шаблоне. Я использую twig-тесты для этого случая

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; })
        ];
    }
}

И в шаблоне

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

Ответ 2

Косвенным способом достижения этого является тестирование объекта для метода, если вы знаете, что каждый унаследованный объект имеет уникальный метод. Возможно, у вашего класса Birthday есть getBirthday(), в то время как ваш класс Walking имеет getMap()?

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

Ответ 3

Использование instanceof в шаблоне неодобрительно с архитектурной точки зрения. Если вы окажетесь в положении, когда вам это нужно, вы, вероятно, обнаружили проблему в своей архитектуре. Ваше решение getType в вашем случае, вероятно, самое лучшее. Вы могли бы поместить это в базовый класс события и прочитать его название класса реализации.

Ответ 4

Я пытаюсь сделать index.html.twig, который перечисляет сущности, которые определены пользователем, и только поля, которые были помечены как 'addToListing' Итак, я дошел до того, что я не знаю что я печатаю.

{% 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 %}

И заголовок бывает \DateTime:/So для такого случая мне нужно будет | дата ( "формат" ) или какое-то лучшее решение.

Какой-нибудь совет для чистого решения для меня?

Ответ 5

У меня была аналогичная проблема, она была связана с наследованием в программном обеспечении отеля. У меня был базовый класс "RoomEquipment", и наследование "Bed", "ElectricAppliances"....

class BaseRoomEquipment {}

class Bed extends BaseRoomEquipment {}

class ElectricAppliances extends BaseRoomEquipment {}

И, конечно, класс "Комната" с отношением OneToMany к RoomEquipment.

В шаблоне я хотел только создать кровати, но комната имеет отношение к базовому оборудованию, которое включает в себя кровати и электроприборы.

Вместо тестирования в шаблоне ветки, в классе Room я создал метод getBeds, и 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....

}

И, конечно же, в Twig:

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

Благодаря компоненту Property Accessor - это возможно. Теперь вашей ветке не нужно проверять тип экземпляра, и он не делает

Ответ 6

Другое решение:

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

то он будет работать с любым классом, который наследует от

class Birthday extends Event {}

class Walking extends Event {}

затем в вашей ветке:

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

ИЛИ

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