2016-10-27 54 views
1

標題有點含糊我知道,但讓我解釋一下我試圖達到的目標。循環通過樹枝中的值並替換空值

我正在嘗試根據從Symfony2 CRM中的原則查詢中提取的數據生成CSV。檢索的數據基於OpenCart產品和屬性數據,以及一些與此問題無關的定製信息。

每個產品最多可以有5個不同的屬性值,分別命名爲A,B,D,L1和L2。但是,有些產品並不是全部,只有A,B和L1。 CSV要求每個屬性值位於單獨的單元格中 - 所以標題如下所示:

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

然後我遍歷我的枝條文件,如下所示:

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

而且我這樣做是對每個可能的屬性名稱,但unfortuantely這行不通,因爲如果名稱不存在,它只是跳過也無妨。如果試圖想通過這些屬性進行循環並在不存在的情況下輸入n/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的產品表,這意味着所有的屬性和鏈接值可以通過這個訪問。

在這方面的任何幫助,非常感謝。

+2

在樹枝編程(與php相比)可能會很痛苦。就我個人而言,我會寫一個接受產品數據作爲輸入的php函數,並返回一個csv就緒數組,其中包含所有五個插槽。 – Cerad

+1

我同意Cerad,'枝'應該用於介紹,而不是修改 – DarkBee

+0

你已經嘗試var_dumping每個變量?我有一個類似的問題,並var_dumped發現,翻譯成你的情況,我必須使用'attribute [0] .text'而不是'attribute.text' – Florian

回答

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是這裏的關鍵...

+0

這是一個好主意,但'row.product.attributes [attribute]'不會存在,因爲A,B,C等在Attributes實體數組中的另一個名爲attributeName的實體中被引用。 –

+0

這就是爲什麼'定義'會跳過整個'if'如果它不存在,對吧? –

+0

不,我的意思是永遠不會存在,因爲屬性名稱在另一個實體中。基本上,使用您建議的代碼每次都沒有結果(即na,na,na,na,na)。假設row.product.attributes有一個數組鍵「A」或「B」等,當它不。 –

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將其與名稱的任何實例一起刪除,因此我最終得到了該值。

一點冗長 - 也許是過度思考 - 解決方案,但它確實有效!