循环遍历树枝中的值并替换空值

时间:2016-10-27 16:24:20

标签: symfony csv twig

我知道标题有点含糊不清,但让我解释一下我想要实现的目标。

我正在尝试根据从我的Symfony2 CRM中的学说查询中提取的数据生成CSV。检索到的数据基于OpenCart产品和属性数据,以及与此问题无关的一些定制信息。

每个产品最多可以有5个不同的属性值,分别为A,B,D,L1和L2。但是,有些产品并不是全部,只有A,B和L1。 CSV要求每个属性值都在一个单独的单元格中 - 所以标题如下:

  

属性:A | ATTRIBUTE:B |属性:D |属性:L1 |   属性:L2

然后我在我的Twig文件中循环,如下所示:

{% for attribute in row.product.attributes %}
    {% if attribute.text is not null %}
        {{ attribute.text }},
    {% else %}na,{% endif %}
{% endfor %}

如果产品具有全部5个属性,则CSV的结构正常。但是,如果产品只有3个属性,则表示所有后续值都被拉回单元格,这意味着其他数据的标题错误。我首先尝试检查值:

{% for attribute in row.product.attributes %}
    {% if attribute.attributeName.name == "A" %}
        {% if attribute.text is not null %}
            {{ attribute.text }},
        {% else %}na,{% endif %}
    {% endif %}
{% endfor %}

我为每个可能的属性名称执行此操作,但不幸的是,这不起作用,因为如果名称不存在,它只是跳过它。我无法想办法绕过这些属性并输入/ a如果它不存在 - 我确定有办法,但我不知道它是什么。

作为参考,以下是为CSV生成数据的控制器代码:

public function adminCsvAction($filter) {

    $repository = $this->getDoctrine()->getRepository('AppBundle:Project');
    $stages_repository = $this->getDoctrine()->getRepository('AppBundle:Stage');
    $users_repository = $this->getDoctrine()->getRepository('AppBundle:User');

    $results = $repository->getSearchResults($filter);
    $users = $users_repository->findAll();
    $stages = $stages_repository->findBy(array('deleted' => 0), array('sortOrder' => 'ASC'));

    $filename = "export_".date("Y_m_d_His").".csv";

    $response = $this->render('AppBundle:pages:csv.html.twig', array('data' => $results,'users' => $users, 'stages' => $stages));
    $response->headers->set('Content-Type', 'text/csv');

    $response->headers->set('Content-Disposition', 'attachment; filename='.$filename);
    return $response;
}

Project实体有各种映射,其中一个映射链接到OpenCart中的Product表,这意味着可以通过它访问所有属性和链接值。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

我也同意Cerad的评论部分 - 这不是Twig的工作。如果你的真的需要这样做,我会尝试大致这样的事情:

{% set allAttr = ["A","B","D","L1","L2"] %}

{% for attribute in allAttr %}
    {% if row.product.attributes[attribute] is defined %}
        {{ row.product.attributes[attribute].text }}
    {% endif %}

    {% if not loop.last %},{% endif %}
{% endfor %}

我想is defined在这里至关重要......

答案 1 :(得分:0)

好的,我明白了。用Jovan Perovic的建议,我想出了这个:

{% set allAttr = ["A","B","D","L1","L2"] %}
{% set prodAtts = [] %}
{% for row in data %}
    {% set existingAtts = [] %}
    {% for att in allAttr %}
        {% if att not in prodAtts %}
            {% set prodAtts = prodAtts|merge([att]) %}
        {% endif %}
    {% endfor %}
    {% for rowAtt in row.product.attributes %}
        {% set existingAtts = existingAtts|merge({(rowAtt.attributeName.name|trim):(rowAtt.attributeName.name|trim~'_'~rowAtt.text|trim)}) %}
    {% endfor %}
    {% for prodAtt in prodAtts %}
        {% if prodAtt not in existingAtts|keys %}
            {% set existingAtts = existingAtts|merge({(prodAtt):(prodAtt~'_na')}) %}
        {% endif %}
    {% endfor %}
        {% set orderedAtts = existingAtts|sort %}
....

然后是每行的循环。我使用带有下划线的属性名称,以便能够对其进行正确排序(因为它只按值排序而不是键)然后使用preg_replace将其与名称的任何实例一起删除,因此我最终得到了值。 / p>

有点冗长 - 可能是过度思考 - 解决方案,但确实有效!