2012-04-11 7 views
16

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

Я также использую 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

ответ

49

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

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 %} 
+0

Я думаю, что я просто плотный , но я, похоже, не могу найти этот класс TwigTest в любом месте в @ fabpot/Twig. Вы определили пользовательский класс, который расширяет '\ Twig_Test', или это псевдоним другого класса? '\ Twig_Test' сам является абстрактным и, следовательно, непрестанным. –

+2

Нашел. Я предполагаю, что класс был переименован в какой-то момент за последние шесть месяцев. '\ Twig_SimpleTest' работает вместо' TwigTest' выше. Смотрите: http://twig.sensiolabs.org/doc/advanced.html#tests –

+1

@TwoWholeWorms Нет, мне просто нравится импортировать их как 'use \ Twig_Test как TwigTest; // или даже «как тест» (и он был скопирован где-то). Вписывается в общий стиль кодирования – KingCrunch

4

Использования InstanceOf в шаблоне неодобрение из АРХИТЕКТУРНОЙ точки зрения. Если вы окажетесь в положении, когда вам это нужно, вы, вероятно, обнаружили проблему в своей архитектуре. Ваше решение getType в вашем случае, вероятно, самое лучшее. Вы все равно можете поместить это в базовый класс события и прочитать его название класса реализации.

5

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

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

Нет никакого волшебного '.method' getter, добавленного Twig к каждому объекту. Так что до тех пор, пока 'yourobject' на самом деле не имеет метода с именем« method », ваше выражение никогда не станет истинным. Вместо этого просто используйте '{% if yourObject.methodName определено%}' где «methodName» - точное имя функции, которую вы проверяете. – flu

+0

Вы правы, я неправильно истолковал некоторые документы –

+0

Для тех, кто хочет знать: Thats называется «Duck-Typing» http://en.wikipedia.org/wiki/Duck_typing :) – KingCrunch

0

Я пытаюсь сделать 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:/Итак, для такого случая мне нужно будет | дата («формат») или какое-то лучшее решение.

Любой совет по чистому решению для меня?

+0

Не будет ли это вышеизложенное решение просто прекрасным, так как это DateTime, который, как вы знаете, имеет метод -> format среди прочего. Если я понимаю ваш пример, то что-то вроде 'if entity.format defined' должно делать трюк! –

+0

Я, я беспокоился о типе заголовка. Я заменил innerHtml с включенным шаблоном, который до сих пор выглядит следующим образом: '{% if bridge.is_scalar (атрибут (объект, заголовок)) или атрибут (объект, заголовок) .__ toString определяется или атрибут (объект, заголовок) is null%} {{attribute (entity, heading)? : 'empty'}} {% else%} {% if bridge.get_class (атрибут (объект, заголовок)) == 'DateTime'%} {# {dump (bridge.get_class (атрибут (объект, заголовок))}} #} {{attribute (entity, heading) | date (dateFormat)}} {% else%} {% endif%} {% endif%} ' – juanmf

+0

здесь Мост: ' пространство имен DocDigital \ Bundle \ DocumentBundle \ Helper; /** * Настя материал для поддержки PHP необходимой в веточке ФНС * * @author Juan Manuel Fernandez <[email protected]> */ класс TwigPhpBridge { функции __call общественности ($ FunctionName, массив $ argV) { return call_user_func_array ($ functionName, $ argV); } } ' – juanmf

0

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

class BaseRoomEquipment {} 

class Bed extends BaseRoomEquipment {} 

class ElectricAppliances extends BaseRoomEquipment {} 

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

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

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

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> 

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

0

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

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 %} 
Смежные вопросы