3

I have a small function which reads a CSV file and outputs all rows after the header.

Now I want to extend this function to accept an location so only rows containing this location are outputted. I'm not exactly sure how I would go about doing this.

Here is the CSV file:

ID,Location,output,wdatatyp,wdb,wbyte,wbit,bitval,rdatatyp,rdb,rbyte,rbit
Lampe1Taster,Wohnzimmer,#output,DB,1,0,0,1,A,0,0,7
Lampe2Ein,Wohnzimmer,#output2,DB,1,0,1,1,A,0,0,6
Lampe2Aus,Küche,#output2,DB,1,0,1,0,A,0,0,6

The location will be the second coloumn. In this case Wohnzimmer and Küche.

Here is the function:

$id = $_GET['location'];
$rows = file('data.csv');
foreach ($rows as $row){
    echo $row;
    list ($id_num) = explode(",", $row);                
    if ($id_num == $id){
        echo $row;
        break;              
    }           
}

This will fetch the row where the FIRST coloumn matches. But I want it to fetch the row where the SECOND coloumn matches.

I will supply the location like so:

plc.php?function=LoadRoom&location=Wohnzimmer

So if the "location" is Wohnzimmer, I need to output to look exactly like so.

Lampe1Taster,Wohnzimmer,#output,DB,1,0,0,1,A,0,0,7
Lampe2Ein,Wohnzimmer,#output2,DB,1,0,1,1,A,0,0,6

Any help at all is appreciated!

Bavilo
  • 389
  • 1
  • 6
  • 19

2 Answers2

3

Maybe instead of complicating your code, you should consider to use built-in PHP fgetcsv() (or str_getcsv, ) function for parsing CSV fields?

Example #1 (handy one liner to parse a CSV file into an array):

$csv = array_map('str_getcsv', file('data.csv'));

Example #2:

$row = 1;
if (($handle = fopen("data.csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        $num = count($data);
        echo "<p> $num fields in line $row: <br /></p>\n";
        $row++;
        for ($c=0; $c < $num; $c++) {
            echo $data[$c] . "<br />\n";
        }
    }
    fclose($handle);
}

Or separate the logic by using the function, e.g.:

/**
 * Convert a csv string, or an array of items which
 * may contain csv strings, into an array of items.
 *
 * @param $args
 *   A simple csv string; e.g. 'a,b,c'
 *   or a simple list of items; e.g. array('a','b','c')
 *   or some combination; e.g. array('a,b','c') or array('a,','b,','c,')
 *
 * @returns array
 *   A simple list of items (e.g. array('a','b','c')
 */
function _convert_csv_to_array($args) {
  //
  // Step 1: implode(',',$args) converts from, say, array('a,','b,','c,') to 'a,,b,,c,'
  // Step 2: explode(',', ...) converts to array('a','','b','','c','')
  // Step 3: array_filter(...) removes the empty items
  // Step 4: array_map(...) trims extra whitespace from each item
  // (handles csv strings with extra whitespace, e.g. 'a, b, c')
  //
  return array_map('trim', array_filter(explode(',', is_array($args) ? implode(',',$args) : $args)));
}

Source: drush.inc

Then you can access the right elements as normally you do for the array elements ($arr[0]).


So based on above, to solve your particular problem, check out the following sample code:

$csv = 'ID,Breich,output,wdatatyp,wdb,wbyte,wbit,bitval,rdatatyp,rdb,rbyte,rbit
Lampe1Taster,Wohnzimmer,#output,DB,1,0,0,1,A,0,0,7
Lampe2Ein,Wohnzimmer,#output2,DB,1,0,1,1,A,0,0,6
Lampe2Aus,Küche,#output2,DB,1,0,1,0,A,0,0,6'; // CSV data

$input = @$_GET['id'] ?: 'Breich'; // input column name
$value = @$_GET['value'] ?: 'Wohnzimmer'; // input value to search

$csv = array_map("str_getcsv", explode(PHP_EOL, $csv));
$keys = array_shift($csv);
$key = array_search($input, $keys);

while ($line = array_shift($csv)) {
    if ($line[$key] == $value) {
        print implode(',', $line) . PHP_EOL;
    }
}

// Outputs:
// Lampe1Taster,Wohnzimmer,#output,DB,1,0,0,1,A,0,0,7
// Lampe2Ein,Wohnzimmer,#output2,DB,1,0,1,1,A,0,0,6
kenorb
  • 155,785
  • 88
  • 678
  • 743
  • Changed my first post a bit and used a different function I already had. Maybe this one will be easier to adapt. – Bavilo Nov 12 '14 at 15:26
  • Ok this works! But how would I assign the parsed CSV data to $csv? – Bavilo Nov 12 '14 at 15:55
  • @Bavilo If you've file as an input (not text), use the code which was in the 1st example. If you have already parsed CSV, it depends in which format you have it, you've try with trial & error. – kenorb Nov 12 '14 at 16:24
  • I have already tried the first example, but $csv = array_map('str_getcsv', file('data.csv')); does not work. $csv does not contain the Array – Bavilo Nov 12 '14 at 16:33
  • @Bavilo Maybe you're using wrong path, try absolute path first (because your PHP instance could use different [cwd](http://php.net/getcwd). If won't work, check: [How do you debug PHP scripts?](http://stackoverflow.com/questions/888/how-do-you-debug-php-scripts), google, try [SO Chat](http://chat.stackoverflow.com/rooms/11/php) or ask another question about specific problem that you're having, because comments are not for solving individual problems. – kenorb Nov 12 '14 at 16:56
0

With my data.csv filled with this:

ID,location,output,wdatatyp,wdb,wbyte,wbit,bitval,rdatatyp,rdb,rbyte,rbit
Lampe1Taster,Wohnzimmer,#output,DB,1,0,0,1,A,0,0,7
Lampe2Ein,Wohnzimmer,#output2,DB,1,0,1,1,A,0,0,6
Lampe2Aus,Küche,#output2,DB,1,0,1,0,A,0,0,6

This works fine.

$csv = file_get_contents('data.csv');               

$input = 'location'; // Welche Spalte soll gelesen werden
$value = $_GET['location']; // Wert dieser Spalte

$csv = array_map("str_getcsv", explode(PHP_EOL, $csv));
$keys = array_shift($csv);
$key = array_search($input, $keys);

while ($line = array_shift($csv)) {
    if ($line[$key] == $value) {
        echo implode(',', $line) . PHP_EOL;
    }
}
Bavilo
  • 389
  • 1
  • 6
  • 19