-1

Here is the full csv file to which this problem pertains.

I don't understand how the error

Warning: array_combine() expects parameter 2 to be array, boolean given in C:\xampp\htdocs\kalugi\auscomp\test.php on line 18

applies in this case, to:

<?php
    // Set header
    function set_header($csv_input, $html_preview) {
        $file = fopen($csv_input, "r");
        while (!feof($file)) {
            $csv_array[] = fgetcsv($file);
        }
        $header = array_shift($csv_array);
        foreach ($csv_array as $product) {
            $headered_array[] = array_combine($header, $product);
        }
        //print_r
        if ($html_preview = 'y') {
            echo '<pre>';
            print_r($headered_array);
            echo '</pre>';
        }
    }

    set_header('ACDataFeed.csv', 'y');
Edit: Every iteration of `print_r($header); print_r($product);` within foreach() loop reveals that both are arrays of the same size:

        Array
    (
        [0] => No_
        [1] => Manufacturer ID
        [2] => Description
        [3] => LQ Price
        [4] => Retail Price Incl_ GST
        [5] => AvailableQty
        [6] => Rocklea
        [7] => Sydney
        [8] => Net Weight
        [9] => Item Category Code
        [10] => Product Group Code
        [11] => Minor Category 1
        [12] => Minor Category 2
        [13] => Vendor Name
        [14] => Vendor URL
        [15] => Item URL
        [16] => Warranty
        [17] => Dimension
        [18] => Description1
        [19] => Image
    )
    Array
    (
        [0] => II00570
        [1] => AUSC00008
        [2] => GNR CAB USB-A-B-5M
        [3] => 6.00000000000000000000
        [4] => 18.00000000000000000000
        [5] => 2.00000000000000000000
        [6] => 1.00000000000000000000
        [7] => 1.00000000000000000000
        [8] => 0.01000000000000000000
        [9] => GNR
        [10] => CAB
        [11] => CAB-USB
        [12] => #
        [13] => 
        [14] => 
        [15] => 
        [16] => 
        [17] => 
        [18] => Generic USB2.0 A-Male to B-Male Printer Cable - 5m

        [19] => https://accomputers.com/uploads/image/GNR-CAB-USB-A-B-5M.jpg
    )

I've considered this through and I'm geniunely unable to see the error here.  How is this false for an array?

Edit 2: Yet the array_combine is successful, despite the error appearing above it. You can see that array $header was successfully combined with array $product below, despite the error:

Warning: array_combine() expects parameter 2 to be array, boolean given in C:\xampp\htdocs\kalugi\auscomp\test.php on line 18

Array
(
    [0] => Array
        (
            [No_] => II00570
            [Manufacturer ID] => AUSC00008
            [Description] => GNR CAB USB-A-B-5M
            [LQ Price] => 6.00000000000000000000
            [Retail Price Incl_ GST] => 18.00000000000000000000
            [AvailableQty] => 2.00000000000000000000
            [Rocklea] => 1.00000000000000000000
            [Sydney] => 1.00000000000000000000
            [Net Weight] => 0.01000000000000000000
            [Item Category Code] => GNR
            [Product Group Code] => CAB
            [Minor Category 1] => CAB-USB
            [Minor Category 2] => #
            [Vendor Name] => 
            [Vendor URL] => 
            [Item URL] => 
            [Warranty] => 
            [Dimension] => 
            [Description1] => Generic USB2.0 A-Male to B-Male Printer Cable - 5m

            [Image] => https://auscompcomputers.com/uploads/image/GNR-CAB-USB-A-B-5M.jpg
        )

    [1] => Array
        (
            [No_] => II00693
            [Manufacturer ID] => M6
            [Description] => ITR KBD M6-PS2-WHT
            [LQ Price] => 8.50000000000000000000
            [Retail Price Incl_ GST] => 24.00000000000000000000
            [AvailableQty] => 202.00000000000000000000
            [Rocklea] => 200.00000000000000000000
            [Sydney] => 2.00000000000000000000
            [Net Weight] => 0.50000000000000000000
            [Item Category Code] => ITR
            [Product Group Code] => KBD
            [Minor Category 1] => KBD-WIRED
            [Minor Category 2] => KBD-SINGLE
            [Vendor Name] => 
            [Vendor URL] => 
            [Item URL] => 
            [Warranty] => 
            [Dimension] => 
            [Description1] => Itron M6 Keyboard, PS2 Beige

            [Image] => https://auscompcomputers.com/uploads/image/ITR-KBD-M6-PS2-WHT.jpg
        )

For completeness, here is the debugging output for:

foreach($csv_array as $product) {
//      $csv_array[][1]
        $headered_array[] = array_combine($header,$product);
        echo '<pre>';
        var_dump($header);
        var_dump($product);
        echo '</pre>';
    }

The var_dumps:

array(20) {
  [0]=>
  string(3) "No_"
  [1]=>
  string(15) "Manufacturer ID"
  [2]=>
  string(11) "Description"
  [3]=>
  string(8) "LQ Price"
  [4]=>
  string(22) "Retail Price Incl_ GST"
  [5]=>
  string(12) "AvailableQty"
  [6]=>
  string(7) "Rocklea"
  [7]=>
  string(6) "Sydney"
  [8]=>
  string(10) "Net Weight"
  [9]=>
  string(18) "Item Category Code"
  [10]=>
  string(18) "Product Group Code"
  [11]=>
  string(16) "Minor Category 1"
  [12]=>
  string(16) "Minor Category 2"
  [13]=>
  string(11) "Vendor Name"
  [14]=>
  string(10) "Vendor URL"
  [15]=>
  string(8) "Item URL"
  [16]=>
  string(8) "Warranty"
  [17]=>
  string(9) "Dimension"
  [18]=>
  string(12) "Description1"
  [19]=>
  string(5) "Image"
}
array(20) {
  [0]=>
  string(7) "II00570"
  [1]=>
  string(9) "AUSC00008"
  [2]=>
  string(18) "GNR CAB USB-A-B-5M"
  [3]=>
  string(22) "6.00000000000000000000"
  [4]=>
  string(23) "18.00000000000000000000"
  [5]=>
  string(22) "2.00000000000000000000"
  [6]=>
  string(22) "1.00000000000000000000"
  [7]=>
  string(22) "1.00000000000000000000"
  [8]=>
  string(22) "0.01000000000000000000"
  [9]=>
  string(3) "GNR"
  [10]=>
  string(3) "CAB"
  [11]=>
  string(7) "CAB-USB"
  [12]=>
  string(1) "#"
  [13]=>
  string(0) ""
  [14]=>
  string(0) ""
  [15]=>
  string(0) ""
  [16]=>
  string(0) ""
  [17]=>
  string(0) ""
  [18]=>
  string(56) "Generic USB2.0 A-Male to B-Male Printer Cable - 5m
"
  [19]=>
  string(65) "https://auscompcomputers.com/uploads/image/GNR-CAB-USB-A-B-5M.jpg"
}
user136649
  • 59
  • 1
  • 7
  • you're probably passing a Boolean instead of an array. – Sfili_81 Jan 22 '20 at 10:24
  • what `var_dump()` says for both `$header` and `$product` within your `foreach()`? – mitkosoft Jan 22 '20 at 10:38
  • @mitkosoft see OP - I have appended on example iteration of the output for `print_r($header); print_r($product); within foreach() loop` – user136649 Jan 22 '20 at 11:18
  • Does this answer your question? [array\_combine() expects parameter 1 to be array, string given](https://stackoverflow.com/questions/29459112/array-combine-expects-parameter-1-to-be-array-string-given) –  Jan 22 '20 at 11:28
  • @Dilek It's a good question and answer, but I don't use `array_map` at all like the question asker? – user136649 Jan 22 '20 at 11:35
  • @user136649, is this error appears on every iteration, or just once? could you please define `$iterator` counter out of your `foreach()`, increment it with 1 inside then echo and debug the arrays on every iteration? I truly believe that you have an extra new line into your file which produce an empty `$product` array member. – mitkosoft Jan 22 '20 at 11:38
  • So what I did was: `foreach($csv_array as $product) { $headered_array[] = array_combine($header,$product); echo '
    ';
      print_r($header);
      print_r($product);
      echo '
    '; }`. So it's printing arrays correctly for every iteration of the foreach loop. In the original code, the error only appears once. Does that answer your question?
    – user136649 Jan 22 '20 at 11:40
  • @user136649, could you please share both arrays when the error appears? – mitkosoft Jan 22 '20 at 11:45
  • See Edit 2 in original post: After the error appears once, the entire successfully array_combined result follows. So the `array_combine` is successful despite the error. – user136649 Jan 22 '20 at 11:54
  • @user136649 Link I gave is about `array_combine();`, anyway can you try like this please without `array_shift();` `$header = $csv_array; foreach ($csv_array as $product) { $headered_array = array_combine($header, $product);` –  Jan 22 '20 at 12:07
  • @Dilek The question you linked is indeed about `array_combine` but the asker's problem was different, as he was also using `array_map` in his code and that turned out to be the problem. Anyway, `$header = $csv_array; foreach ($csv_array as $product) { $headered_array = array_combine($header, $product);}` gives `Warning: array_combine(): Both parameters should have an equal number of elements in C:\xampp\htdocs\kalugi\auscomp\test.php on line 28` – user136649 Jan 22 '20 at 12:17
  • @Dilek - here is the full csv file, why don't you try yourself: [download here](https://www.dropbox.com/s/6qjthgkpany1kvh/AuscompDataFeed.csv?dl=0) – user136649 Jan 22 '20 at 12:22
  • I think I solved it guys. Upvote if you like my solution because I got slammed earlier with downvotes and it turned out to be an instructive question and answer. – user136649 Jan 22 '20 at 16:35

2 Answers2

0

This turns out to be a really good question as you'll see in the following solution.

It's a common pitfall of csv files that a redundant line terminator at the end actually causes an empty array to be written when using PHP's inbuilt csv-to-array functions such as fgetcsv, which are very basic and do not take such things into account.

From PHP Manual for array_combine:

5.4.0 Previous versions issued E_WARNING and returned FALSE for empty arrays.

This matches the fact that the error was only returned once for the whole foreach loop that was compiling the array, since there was only one empty array at the end of the csv file. It also explains why the array_combined actually succeeded with all but the last element case.

See that last array is empty:

...
    [8405] => Array
        (
            [No_] => II38392
            [Manufacturer ID] => 7XB7A00034
            [Description] => LEN HDD SAS-1TB-7XB7A00034
            [LQ Price] => 336.00000000000000000000
            [Retail Price Incl_ GST] => 480.48000000000000000000
            [AvailableQty] => 0.00000000000000000000
            [Rocklea] => 
            [Sydney] => 
            [Net Weight] => 0.50000000000000000000
            [Item Category Code] => LEN
            [Product Group Code] => HDD
            [Minor Category 1] => HDD-2.5
            [Minor Category 2] => HDD-ENT
            [Vendor Name] => Lenovo
            [Vendor URL] => 
            [Item URL] => 
            [Warranty] => 3 Years
            [Dimension] => 
            [Description1] => Lenovo 7XB7A00034, ThinkSystem 2.5" 1TB 7.2K SAS 12Gb Hot Swap 512n HDD, 3 Years

            [Image] => https://auscompcomputers.com/uploads/image/LEN-HDD-SAS-1TB-7XB7A00034.jpg
        )

    [8406] => 
    )

Solution - treat the file first before passing it into any further functions:

function remove_last_n($csv_input){
    //remove the very last newline to prevent a 0-field array for the last line
    $str = file_get_contents($csv_input);
    $str = preg_replace('/\n$/', '', $str);
    file_put_contents("$csv_input",$str);
}
remove_last_n('whatever_file.csv');
user136649
  • 59
  • 1
  • 7
0

See user136649's explanation.

in my case I need the array before putting it into a file, so I did the following and checked for the last empty row

$stream = fopen('filepath', 'r');
if ($stream) {
    $header = [];
    $count = 0;
    while (!feof($stream)) {
        $row = fgetcsv($stream, 0, ';');
        if (empty($header)) {
            $header = $row;
        } elseif (empty($row)) {
            continue;
        } else {
            $csv[] = array_combine($header, $row);
        }
    }
} else {
    throw new Exception($stream . ' doesn`t exist or is not readable.');
}
fclose($stream);
Brncnnr
  • 1
  • 1