PHP循环 - 使用数组中的最后一个非空值

时间:2016-12-10 09:52:45

标签: php arrays loops magento

我很难道歉,如果这很难理解,很难解释,我是PHP开发的新手。我有一个脚本,它逐行读取CSV文件并将每一行存储在一个数组中。 CSV文件的格式如下(3列示例):

enter image description here

这些行然后通过循环运行,将产品导出到Magento API。请参阅下面的代码:

<?php
    // Interpret the CSV file and store each row as an array.
    $csv = array();
    $new_csv = array();

    if (FALSE !== $handle = fopen("http://csvfilelink.csv", "r")) {
        while (FALSE !== $row = fgetcsv($handle)) {
            $csv[] = $row;
        }
    }

    foreach ($csv as $row) {
        $new_row = array();
        for ($i = 0, $c = count($csv[0]); $i < $c; ++$i) {
            $new_row[$csv[0][$i]] = $row[$i]; 
        }
        $new_csv[] = $new_row;
    }

    // Create client session.
    $client = new SoapClient('API-URL');
    $sessionId = $client->login('User', 'Pass');

    // Product variables.
    $attributeSets = $client->catalogProductAttributeSetList($sessionId);
    $attributeSet = current($attributeSets);
    $total_rows = count($csv);

    // Create Products from CSV.
    for ($sku = 1, $name = 1, $price = 1, $desc = 1, $table = 1, $qty = 1, $cond = 1, $pos = 1, $image = 1, $brand = 1, $color = 1, $material = 1, $style = 1;
        $sku < $total_rows, $name < $total_rows, $price < $total_rows, $desc < $total_rows, $table < $total_rows, $qty < $total_rows, $cond < $total_rows, $pos < $total_rows, $image < $total_rows, $brand < $total_rows, $color < $total_rows, $material < $total_rows, $style < $total_rows;
        ++$sku, ++$name, ++$price, ++$desc, ++$table, ++$qty, ++$cond, ++$pos, ++$image, ++$brand, ++$color, ++$material, ++$style) {

        if ($new_csv[$sku]['Product SKU'] != '') {
            try {
                // Create product data.
                $client->catalogProductCreate($sessionId, 'simple', $attributeSet->set_id, $new_csv[$sku]['Product SKU'], array(
                    'name' => $new_csv[$name]['Product Name'],
                    'price' => $new_csv[$price]['Price'],
                    'categories' => array(
                        'category' => 'DifferentCategory'
                    ),
                    'description' => $new_csv[$desc]['Product Description (Including HTML)'] . "<br><br>" . $new_csv[$table]['Param table'],
                    'weight' => 1,
                    'status' => 1,
                    'visibility' => 4,
                    'tax_class_id' => 1,
                    'stock_data' => array(
                        'qty' => $new_csv[$qty]['Stock Quantity'],
                        'is_in_stock' => 1
                    ),
                    'additional_attributes' => array(
                        'single_data' => array(
                            array('key' => 'condition', 'value' => $new_csv[$cond]['Condition (Including HTML)']),
                            array('key' => 'brand', 'value' => $new_csv[$brand]['Brand']),
                            array('key' => 'color', 'value' => $new_csv[$color]['Color']),
                            array('key' => 'material', 'value' => $new_csv[$material]['Material']),
                            array('key' => 'style', 'value' => $new_csv[$style]['Style'])
                        )
                    )
                ),0);

                // Add product images.
                $client->catalogProductAttributeMediaCreate($sessionId, $new_csv[$sku]['Product SKU'], array(
                    'file' => array(
                        'content' => base64_encode(file_get_contents($new_csv[$image]['Main Image'])),
                        'mime' => 'image/png',
                    ),
                    'position' => $new_csv[$pos]['Image Rank Position'],
                    'types' => array('image')
                ), 0);

                // Echo success message.
                echo '<div class="success_box"><span class="success_box_text"><b>Success:</b> Product <b>' . $new_csv[$sku]['Product SKU'] . '</b> has been created.</div>';
            } catch (SoapFault $e) {
                // Echo error message.
                echo '<div class="error_box"><span class="error_box_text"><b>Error:</b> Cannot create product <b>' . $new_csv[$sku]['Product SKU'] . '</b> - ' . $e->getMessage() . '.</span></div>';
            }
        } else {
            $client->catalogProductAttributeMediaCreate($sessionId, $new_csv[$sku]['Product SKU'], array(
                'file' => array(
                    'content' => base64_encode(file_get_contents($new_csv[$image]['Main Image'])),
                    'mime' => 'image/png',
                ),
                'position' => $new_csv[$pos]['Image Rank Position'],
                'types' => array('image')
            ), 0);
        }
    }

?>

这适用于只有1个产品图片的产品,但我意识到我需要处理只填充了Product Image列的行,因为这些图像需要添加到之前的同一产品中在前一个循环中执行catalogProductCreate时创建的。为了尝试处理这个问题,我添加了一个if/else语句,用于标识Product SKU列中的当前值是否为空,然后如果它不为空,则仅执行catalogProductAttributeMediaCreate代码。< / p>

这个问题是循环递增$sku变量,因此当执行else语句时,脚本会尝试将图像添加到{{1}的当前值同一行中的列,因此抛出了无效的数据错误。

我无法弄清楚如何让脚本返回到最后一个非空Product SKU值,以便将图像添加到该产品而不是返回错误。我可能不得不删除Product SKU语句,因为它不会像我最初希望的那样处理问题(愚蠢地没有意识到变量会随着每个循环而增加)。但是我想,在其他地方仍然需要if/else行才能使用。

我愿意接受任何有关如何克服这一点的想法。我提前感谢您提供的任何见解。如果不清楚需要澄清,请告诉我,谢谢!

1 个答案:

答案 0 :(得分:1)

我认为您可以简化代码:)

1。来源数据

<?php

$data = [
  ['1', 'Product1', 'value1.1'],
  ['',   '',        'value1.2'], // there is no value on columns 0 & 1 => take last with
  ['',   '',        'value1.3'], // there is no value on columns 0 & 1 => take last with
  ['2', 'Product2', 'value2.1'],
  ['',   '',        'value2.2'], /// idem
];

?>

通过CSV功能提取您自己的功能

2。读取数据

之后,你可以选择一个逻辑:

  • 为每列
  • 取一个正确的值
  • 使用正确的值获取前一个值,其中ID列有效(对于ex)。
  • ...

我会回答第一个问题:)

<?php
/**************************************************************
 * FUNCTION getPreviousColumnValue                            *
 **************************************************************
 * This function return the previous valid value on array     *
 * list, on the selected colum. A valid value is something    *
 * not null or different of '' (empty).                       *
 **************************************************************
 * @param array $data: array source, multidim                 *
 * @param int $from: current line. Will extract sub array     *
 * from 0 to $from.                                           *
 * @param int $column: column index to analyze.               *
 **************************************************************
 * Examples:                                                  *
 *  - getPreviousColumnValue($data, 3, 0)                     *
 *     On $data, from line 3, return the previous  correct    *
 *     value for column 0 on $data array                      *
 **************************************************************/
function getPreviousColumnValue(array $data, $from, $column) {
    $data = array_slice($data, 0, $from + 1); // extract sub data array. $from id the current line
    $data = array_reverse($data); // reverse for analyze

    // Loop on each reversed line (from 0 to $from)
    foreach( $data as $row ) {
        // If the index does not exist, skip
        if( !isset($row[$column]) ) continue;

        // If the value (is null or empty) and different of '0', skip
        if( is_null($row[$column]) OR $row[$column] === '' ) continue;

        // Else, return this value !
        return $row[$column];
    }
    return null; // Null, there is no value :(
}

// Read CSV data - this is your code !
foreach( $data as $iLineNumber => $line ) {

    // Include this loop at the begenning of you code
    // Iterate on each row of the line:
    foreach( $line as $iRowKey => $row ) {
        // If the value (is null or empty) and different of '0' ...
        // ... we need to find the previous valid value
        if( is_null($row) OR $row === '' ) {
            $line[$iRowKey] = getPreviousColumnValue($data, $iLineNumber, $iRowKey);
        }
        // So, if value is valid => use it ; else, find correct one via the function
    }

    // Your code here ! The array is fully filled.
    // $client->catalogProductCreate(...)
    var_dump($line);
}

最终输出:

array (size=3)
  0 => string '1' (length=1)
  1 => string 'Product1' (length=8)
  2 => string 'value1.1' (length=8)

array (size=3)
  0 => string '1' (length=1)
  1 => string 'Product1' (length=8)
  2 => string 'value1.2' (length=8)

array (size=3)
  0 => string '1' (length=1)
  1 => string 'Product1' (length=8)
  2 => string 'value1.3' (length=8)

array (size=3)
  0 => string '2' (length=1)
  1 => string 'Product2' (length=8)
  2 => string 'value2.1' (length=8)

array (size=3)
  0 => string '2' (length=1)
  1 => string 'Product2' (length=8)
  2 => string 'value2.2' (length=8)

这是你需要的吗?