使用多个数据源编译复杂数组

时间:2016-05-26 15:11:39

标签: php arrays simplexml

我遇到了一些构建相当复杂阵列的问题。我做了4个不同的API调用,每个调用都返回了simpleXML数据 将在下面显示。

通过一次API调用,我基本上得到了一堆潜在客户。对于每个潜在客户,我需要收集该潜在客户的任何数据。 这是潜在客户的示例回复。

SimpleXMLElement {#289 ▼
  +"Leads": SimpleXMLElement {#297 ▼
    +"Lead": array:12 [▼
      0 => SimpleXMLElement {#300 ▼
        +"ID": "1266283"
        +"State": "Current"
        +"Name": "Test project"
        +"Description": "Test project"
        +"EstimatedValue": "2.00"
        +"Date": "2016-05-26T00:00:00"
        +"Client": SimpleXMLElement {#316 ▼
          +"ID": "8549201"
          +"Name": "Test Client"
        }
      }
    ]
  }
}

然后我有一堆客户端XML数据。我需要将Lead链接到客户端并收集一些客户端数据。这是客户端的示例数据部分。

SimpleXMLElement {#290 ▼
  +"Clients": SimpleXMLElement {#298 ▼
    +"Client": array:41 [▼
      34 => SimpleXMLElement {#335 ▼
        +"ID": "8549201"
        +"Name": "Test Client"
        +"IsProspect": "No"
        +"BusinessStructure": "IT"
      }
    ]
  }
}

所以在这一点上,我有Leads并且我已将正确的客户端与Lead匹配并获得有关该客户端的数据。嵌套两个API调用引用引号。 一个API调用返回所有当前行情。另一个API调用返回草稿引号。

这是当前报价

的示例
SimpleXMLElement {#291 ▼
  +"Quotes": SimpleXMLElement {#299 ▼
    +"Quote": array:24 [▼
      0 => SimpleXMLElement {#302 ▼
        +"ID": "Q12415"
        +"Type": "Quote"
        +"State": "Issued"
        +"Name": "Test Quote"
        +"LeadID": "1266283"
        +"Date": "2016-05-20T00:00:00"
        +"Amount": "6100.00"
        +"AmountTax": "1220.00"
        +"AmountIncludingTax": "7320.00"
        +"Client": SimpleXMLElement {#331 ▼
          +"ID": "8549201"
          +"Name": "Test Client"
        }
      }
    ]
  }
}

这是草稿报价

的示例
SimpleXMLElement {#292 ▼
  +"Quotes": SimpleXMLElement {#300 ▼
    +"Quote": SimpleXMLElement {#303 ▼
      +"ID": "Q12456"
      +"Type": "Quote"
      +"State": "Draft"
      +"Name": "Test project"
      +"LeadID": "1266283"
      +"Date": "2016-05-26T00:00:00"
      +"Amount": "2000.00"
      +"AmountTax": "400.00"
      +"AmountIncludingTax": "2400.00"
      +"Client": SimpleXMLElement {#305 ▼
        +"ID": "8549201"
        +"Name": "Test Client"
      }
    }
  }
}

无论如何,这就是我目前所拥有的

public function getForecastReportForLeads() {
    $getCurrentLeads = Helper::getCurrentLeads();
    $currentLeadsXML = new \SimpleXMLElement($getCurrentLeads);

    $getCurrentClients = Helper::getClientList();
    $currentClientsXML = new \SimpleXMLElement($getCurrentClients);

    $getCurrentQuotes = Helper::getCurrentQuotes();
    $currentQuotesXML = new \SimpleXMLElement($getCurrentQuotes);

    $getDraftQuotes = Helper::getDraftQuotes();
    $draftQuotesXML = new \SimpleXMLElement($getDraftQuotes);

    $forecastArray = array();
    $iterator = 0;

    foreach($currentLeadsXML->Leads->Lead as $lead) {
        $seconditerator = 0;
        $thirditerator = 0;
        $fourthiterator = 0;

        $dateIdentified = date("d/m/Y", strtotime($lead->Date));
        $forecastArray[$iterator]["leadData"] = array(
            'LeadID' => (string)$lead->ID,
            'DateIdentified' => $dateIdentified,
            'Client' => (string)$lead->Client->Name,
            'LeadName' => (string)$lead->Name,
            'Owner' => (string)$lead->Owner->Name,
            'Category' => (string)$lead->Category
        );

        foreach ($currentClientsXML->Clients->Client as $client) {
            if((string)$lead->Client->Name == $client->Name) {
                $forecastArray[$iterator]["clientData"] = array(
                    'BusinessStructure' => (string)$client->BusinessStructure,
                    'IsProspect' => (string)$client->IsProspect
                );
                $seconditerator++;
            }
        }

        foreach ($currentQuotesXML->Quotes->Quote as $quote) {
            if ((string)$lead->ID == (string)$quote->LeadID) {
                $forecastArray[$iterator]["quoteDataIssued"] = array(
                    'QuoteID' => (string)$quote->ID,
                    'ProjectName' => (string)$quote->Name,
                    'Amount' => (string)$quote->Amount,
                    'AmountTax' => (string)$quote->AmountTax,
                    'AmountIncludingTax' => (string)$quote->AmountIncludingTax
                );
                $thirditerator++;
            }
        }

        foreach ($draftQuotesXML->Quotes->Quote as $draftQuote) {
            if ((string)$lead->ID == (string)$draftQuote->LeadID) {
                $forecastArray[$iterator]["quoteDataDraft"] = array(
                    'QuoteID' => (string)$draftQuote->ID,
                    'ProjectName' => (string)$draftQuote->Name,
                    'Amount' => (string)$draftQuote->Amount,
                    'AmountTax' => (string)$draftQuote->AmountTax,
                    'AmountIncludingTax' => (string)$draftQuote->AmountIncludingTax
                );
                $fourthiterator++;
            }
        }
        $iterator++;
    }

    return $forecastArray;
}

有一点需要注意的是,有时报价​​没有LeadID。如果是这种情况,可以忽略Quote,这是我目前没有处理的事情。

另一件需要注意的事情是,如果与潜在客户相关的客户端的IsProspect值为“否”,我只想获取此数据。这是我正在努力实现的其他方面。

任何有关根据我的要求正确使用此建议的建议,或我如何 非常感谢我对当前代码的改进。

非常感谢

1 个答案:

答案 0 :(得分:1)

小清理

摆脱计数器,代码将更具可读性:

function getForecastReportForLeads()
{

    /* ... */

    $forecastArray = array();

    foreach($currentLeadsXML->Leads->Lead as $lead) {

        $reportItem = array;

        $dateIdentified = date("d/m/Y", strtotime($lead->Date));
        $reportItem["leadData"] = array(/* ... */);

        foreach ($currentClientsXML->Clients->Client as $client) {
            if((string)$lead->Client->Name == $client->Name) {
                $reportItem["clientData"] = array(/* ... */);
                if ('No' != (string)$client->IsProspect) {
                     continue;
                }
            }
        }

        foreach ($currentQuotesXML->Quotes->Quote as $quote) {
            if ((string)$lead->ID == (string)$quote->LeadID) {
                $forecastArray["quoteDataIssued"][] = array(/* ... */);
            }
        }

        foreach ($draftQuotesXML->Quotes->Quote as $draftQuote) {
            if ((string)$lead->ID == (string)$draftQuote->LeadID) {
                $reportItem["quoteDataDraft"][] = array(/* ... */);
            }
        }

        $forecastArray[] = $reportItem;
    }

    return $forecastArray;
}

要省略prospect!=No客户端,请转到:

if ('No' != (string)$client->IsProspect) {
    continue;
}

如上所示。只要每个潜在客户都有一个客户端,这将有效。

更大的重构

第二种选择。要改进该代码,您可以尝试移动逻辑,负责遍历XML并将XML转换为数组以分离类。每个数据集合一个类。所以这里有可能的类结构:

class LeadsCollection
{

    function __construct(\SimpleXMLElement $leads){}

    /**
     * Returns list of leads in form of assoc arrays.
     *
     * @return array
     */
    function asArray(){}

}


class ClientsCollection
{

    function __construct(\SimpleXMLElement $clients){}

    /**
     * @return array
     */
    function getClientByName($name){}

    /**
     * retub bool
     */
    function isProspect($name){}

}

class QuotesCollection
{

    function __construct(\SimpleXMLElement $quotes){}

    /**
     * @retun array|null - list of quotes related with given lead
     */
    function getQuotesByLeadId($leadId){}

}

class DraftQuotesCollection
{

    function __construct(\SimpleXMLElement $draftQuotes){}

    /**
     * @retun array|null - list of draft quotes related with given lead
     */
    function getDraftQuotesByLeadId($leadId){}
}

然后你的数组创建代码将更清晰,更简洁:

function getForecastReportForLeads() {
    $leads = new LeadsCollection(new \SimpleXMLElement(Helper::getCurrentLeads()));
    $clients = new ClientsCollection(new \SimpleXMLElement(Helper::getClientList());
    $quotes = new QuotesCollection(new \SimpleXMLElement(Helper::getCurrentQuotes()));
    $draftQuotes = new DraftQuotesCollection(Helper::getDraftQuotes(new \SimpleXMLElement(Helper::getDraftQuotes())));

    $report = array();
    foreach ($leads->asArray() as $lead) {

        if ($clients->isProspect($lead['Client'])) {
            continue;
        }

        $clientData = $clients->getClientByName($lead['Client']);
        $quotesData = $quotes->getQuotesByLeadId($lead['LeadId']);
        $draftQuotesData = $draftQuotes->getDraftQuotesByLeadId($lead['LeadId']);

        $reportItem = array(
            'leadData' => $lead,
            'clientData' => $clientData,
        );

        empty($quotesData) || $reportItem['quoteDataIssued'] = $quotesData;
        empty($draftQuotesData) || $reportItem['quoteDataDraft'] = $draftQuotesData;

        $report[] = $reportItem;
    }

    return $report;
}

第三种方式

如果出于任何原因,您不想将4个新类放入项目中,那么您可以尝试将monolith方法分解为几个私有方法。您甚至可以关注" design"以上建议,但您可以将所有方法都放在单个类中,而不是有4个类。不是最干净的解决方案,但仍然比在风格方法中有一个大的程序。如果您知道不需要在系统的任何其他位置重用该代码,那么这是有意义的。

说明

根据数据的大小,您一次又一次地遍历整个数据集的方法可能不是最有效的:

        foreach ($currentClientsXML->Clients->Client as $client) {
            if((string)$lead->Client->Name == $client->Name) {
                 /* ... */

如果您根据要访问的变量重新排列/分组潜在客户和引号,可能会获得回报,因此leadId也是如此。和client name