编译具有多个数据源的复杂数组
Compiling complex array with multiple data sources
我在构建相当复杂的数组时遇到了一些问题。我进行了 4 个不同的 API 调用,每个调用 return 简单 XML 数据
将在下面显示。
通过一个 API 电话,我基本上 return 获得了一堆线索。对于每个潜在客户,我需要为该潜在客户收集我能收集的所有数据。
这是潜在客户的示例响应。
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数据。我需要 link 将线索交给客户并收集一些客户数据。这是客户的示例数据部分。
SimpleXMLElement {#290 ▼
+"Clients": SimpleXMLElement {#298 ▼
+"Client": array:41 [▼
34 => SimpleXMLElement {#335 ▼
+"ID": "8549201"
+"Name": "Test Client"
+"IsProspect": "No"
+"BusinessStructure": "IT"
}
]
}
}
所以此时,我有潜在客户,并且我已将正确的客户与潜在客户相匹配,并获得了有关该客户的数据。嵌套的两个 API 调用指的是行情。
一个 API 调用 return 所有当前行情。另一个 API 调用 return 的报价草案。
这是当前报价的示例
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。如果是这种情况,可以忽略报价,这是我目前不处理的事情。
另一件需要注意的事情是,如果潜在客户相关的客户也具有 "No" 的 IsProspect 值,我只想获取此数据。这是我正在努力实现的另一件事。
任何关于根据我的要求正确设置它的建议,或者我如何能
非常感谢改进我当前的代码。
非常感谢
小清理
只需去掉计数器,代码将更具可读性:
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 转换为数组的逻辑以分隔 classes。每个数据收集一个 class。所以这里是这样的 classes 的可能结构:
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 个新的 classes 放入您的项目中,那么您可以尝试将单体方法分解为多个私有方法。您甚至可以按照上面建议的 "design" 进行操作,但您可以将所有方法都放在一个中,而不是使用 4 个 class 方法。不是最干净的解决方案,但仍然比在样式方法中使用一个大的程序要好。如果您知道您不需要在系统的任何其他地方重用该代码,那么这也是有意义的。
备注
根据您的数据大小,您一次又一次遍历整个数据集的方法可能不是最有效的:
foreach ($currentClientsXML->Clients->Client as $client) {
if((string)$lead->Client->Name == $client->Name) {
/* ... */
如果您 rearrange/group 通过变量引导和引用您想要访问它,那么通过 leadId
可能会有所回报。和 client name
.
我在构建相当复杂的数组时遇到了一些问题。我进行了 4 个不同的 API 调用,每个调用 return 简单 XML 数据 将在下面显示。
通过一个 API 电话,我基本上 return 获得了一堆线索。对于每个潜在客户,我需要为该潜在客户收集我能收集的所有数据。 这是潜在客户的示例响应。
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数据。我需要 link 将线索交给客户并收集一些客户数据。这是客户的示例数据部分。
SimpleXMLElement {#290 ▼
+"Clients": SimpleXMLElement {#298 ▼
+"Client": array:41 [▼
34 => SimpleXMLElement {#335 ▼
+"ID": "8549201"
+"Name": "Test Client"
+"IsProspect": "No"
+"BusinessStructure": "IT"
}
]
}
}
所以此时,我有潜在客户,并且我已将正确的客户与潜在客户相匹配,并获得了有关该客户的数据。嵌套的两个 API 调用指的是行情。 一个 API 调用 return 所有当前行情。另一个 API 调用 return 的报价草案。
这是当前报价的示例
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。如果是这种情况,可以忽略报价,这是我目前不处理的事情。
另一件需要注意的事情是,如果潜在客户相关的客户也具有 "No" 的 IsProspect 值,我只想获取此数据。这是我正在努力实现的另一件事。
任何关于根据我的要求正确设置它的建议,或者我如何能 非常感谢改进我当前的代码。
非常感谢
小清理
只需去掉计数器,代码将更具可读性:
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 转换为数组的逻辑以分隔 classes。每个数据收集一个 class。所以这里是这样的 classes 的可能结构:
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 个新的 classes 放入您的项目中,那么您可以尝试将单体方法分解为多个私有方法。您甚至可以按照上面建议的 "design" 进行操作,但您可以将所有方法都放在一个中,而不是使用 4 个 class 方法。不是最干净的解决方案,但仍然比在样式方法中使用一个大的程序要好。如果您知道您不需要在系统的任何其他地方重用该代码,那么这也是有意义的。
备注
根据您的数据大小,您一次又一次遍历整个数据集的方法可能不是最有效的:
foreach ($currentClientsXML->Clients->Client as $client) {
if((string)$lead->Client->Name == $client->Name) {
/* ... */
如果您 rearrange/group 通过变量引导和引用您想要访问它,那么通过 leadId
可能会有所回报。和 client name
.