Что является более эффективным: заполнение переменных с помощью прутьевых фильтров или передача их через контроллер? - PullRequest
0 голосов
/ 28 сентября 2019

Я недавно использовал свои собственные фильтры для веточек.Я также искал способы улучшить свою производительность.

Я изо всех сил пытаюсь различить, когда мне нужно создать функцию в Сервисе, которая затем используется Контроллером или если я должен сделать этовместо этого фильтр веточки.Мне интересно, какой из них выполняется быстрее или есть какая-либо разница?Чтобы прояснить мой вопрос, я хочу показать, как я заполняю переменные фотографии обоими.

Шаблон веточки будет выглядеть следующим образом.Он просто создаст элементы изображения с массивом фотографий.

/ content / photos.html.twig

    {% for photo in photos %}
    <img class="lozad card-img read-more-card-item-img" data-src="{{ photo }}">  
    {% endfor %}

Метод 1: Передайте переменную photos вконтроллер.Контроллер, вероятно, будет использовать службу PhotoService и вызывать функцию getReadMore, передавая ее шаблону ветки:

 function controllerAction(){
           $response = $this->render(
                '/content/photos.html.twig',
                 array(
                    'photos' => $photoService->getReadMorePhotos($posts),
                    'loadMoreUrl' => $url,
                    'limit' => $limit
                )
    }

Метод 2. Вместо этого используйте пользовательский фильтр ветки:

public function getFilters()
 {
return array (new \Twig\TwigFilter('readMorePhotos', array($this, 'getReadMorePhotos')));
}

 //Twig filter
    public function getReadMorePhotos($posts)
    {
...
        $photos = [];
        foreach ($posts as $post) {
             $image = $this->getAbsoluteThumbsPath($post->getImage());
             if ($image != null && $image != "" && strpos($image, '/img/posts/default-post.png') === false) {
                  $gallery[] = $image;
             }
        }
...
        return $photos;
    }

В шаблоне ветки переменная photos будет заполнена следующим образом:

{{set photos = posts|readMorePhotos}}

Есть ли разница в обоих методах?

1 Ответ

1 голос
/ 28 сентября 2019

очень самоуверенный, так что этот ответ по сути ... является мнением.

в моем понимании: чем больше нестандартных функций / фильтров используется в шаблоне, тем хуже вы семантически,С одной стороны, тот, кто редактирует или создает шаблоны, должен знать об этих функциях / фильтрах, что, на мой взгляд, нежелательно.

Кроме того, как уже упоминалось в комментарии к вопросу в DarkBee, фильтры предназначены дляпреобразование данных, а не получение их.функция ветки была бы более подходящей, но мне она тоже не нравится по вышеуказанной причине (она также предоставляет все шаблоны для этой функции, если не приняты меры предосторожности, с другой стороны, ожидаетсясуществует во всех шаблонах).

С другой стороны, редактор / создатель шаблонов также должен знать, какие переменные могут существовать в текущем контексте.Таким образом, в конечном счете, требуется предварительное знание.

Я хочу предложить немного другой (и, по моему высокомерному, но скромному мнению, вариант лучше ) ...

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

 {% for photo in post.photos %}
       {# display of photos #}
 {% endfor %}

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

 {% for photo in posts.photos %}

, который, конечно, имеет другую семантику и действительно представляет собой винты с массивом posts, где photos - один элемент.Тем не менее, представьте, что коллекция является объектом, который имеет дополнительные функции (я буду бессовестно расширять доктрину ArrayCollection):

 <?php

 namespace App\Collection;

 use Doctrine\Common\Collections\ArrayCollection;
 use App\Service\PhotoService;

 class PostCollection extends ArrayCollection {
     public $photoService;

     public function __construct(array $elements, PhotoService $photoService) {
         parent::__construct($elements);
         $this->photoService = $photoService;
     }

     public function getPhotos() {
         return $this->photoService->getReadMorePhotos($this->toArray())
     }
 }

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

$response = $this->render(
    '/content/photos.html.twig',
    array(
        'posts' => new PostCollection($posts, $photoService),
        'loadMoreUrl' => $url,
        'limit' => $limit
    )
);

и может быть использован, как написано выше.

Почему это работает?ArrayCollection реализует несколько интерфейсов, среди которых есть ArrayAccess, а также IteratorAggregate (что расширяет Traversable), который позволяет вам использовать его в цикле, и он будет предоставлять коллекцию, которую он дал в своем конструкторе (или который изменяется в методах модификации), если возникнет такая необходимость, вы всегда можете получить массив с помощью ArrayCollection::toArray.

Зачем это?Чтобы получить чистый код.

Должен ли я это сделать?НетНо это отчасти из-за моей привычки реализовывать почти все отношения в базе данных, которые в сочетании с ORM дают мне это бесплатно.

...