-1

我最近一直在使用自己定制的树枝过滤器。我也一直在寻找提高表现的方法。

我很难区分何时应该在服务中构建函数,然后由控制器使用,或者是否应该将其改为树枝过滤器。我想知道哪个执行得更快,或者是否有任何区别?为了澄清我的问题,我想展示如何用两者填充可变照片。

树枝模板将如下所示。它只会用照片数组制作图像元素。

/content/photos.html.twig

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

方法 1:在控制器中传递照片变量。控制器可能会使用名为 PhotoService 的服务并调用 getReadMore 函数,同时将其传递给 twig 模板:

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

在 twig 模板中,photos 变量将像这样填充:

{{set photos = posts|readMorePhotos}}

两种方法有什么区别吗?

4

1 回答 1

1

非常固执己见,所以这个答案本质上......是一种观点。

我的看法:模板中使用的非标准函数/过滤器越多,语义上的情况就越糟糕。一方面,编辑或创建模板的人必须知道那些功能/过滤器,在我看来,这是不可取的。

此外,正如 DarkBee 在问题评论中已经提到的那样,过滤器用于转换数据,而不是获取数据。twig 函数会更合适,但由于上述原因,我也不喜欢它(它也将所有模板暴露给该函数,除非采取预防措施,另一方面,它应该存在于所有模板中) .

另一方面,模板编辑器/创建者还必须知道当前上下文中可能存在哪些变量。所以最终需要一些先验知识。

我想提出一个稍微不同的(在我傲慢但谦虚的观点中也更好)的选择......

据我所知,如果你可以使用它会更好

 {% 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实现了一些接口,其中有ArrayAccessas IteratorAggregate(其中 extends Traversable),它允许您在循环中使用它,并且它将提供它在其构造函数中给出的集合(或在修改方法中更改),如果需要时,您始终可以通过ArrayCollection::toArray.

为什么要这样做?获得干净的代码。

我这样做吗?不,待定。但这部分是由于我习惯于实现数据库中几乎所有的关系,结合 ORM 可以免费为我提供一些。

于 2019-09-28T09:25:56.443 回答