0

I am working on Export to CSV in PHP. I have code that works fine it gives me output in ExcelSheet as I want. Code snippet:

public function generate_csv() {
 $data_rows = array();
   $table = 'ProductDetails';
    $data_rows = array();
    global $wpdb, $bp;
    $data= $wpdb->get_results("SELECT * FROM " . $table . "");
    $fh = @fopen( 'php://output', 'w' );

foreach ($data as $u ) {
        $row = array();
        $row[0] = $u->productCode;
        $row[1] = $u->productTitle;
        $row[2] = $u->productDescription;
        $row[3] = $u->specification;
        $row[4] = $u->whereToBuy;       
        $data_rows[] = $row;
    }

  header("Pragma: public");
      ... Some more header ...
  header("Content-Transfer-Encoding: binary");

  fputcsv( $fh, $header_row );
  foreach ( $data_rows as $data_row ) {
         fputcsv( $fh, $data_row );
  }
   fclose( $fh );
   die();
 } 

As you can see in code I am hard coding all column names and creating array. The problem is if phpMyAdmin add/remove column in database then to get perfect ExcelSheet necessary changes need to make in this code also. Can any one please help me to make this code dynamic.? Like what should be instead of $row[0], $row[1], $row[2].... ??

Thank You

Pro-n-apps
  • 55
  • 12
  • If your table schema changes that often, or people don't communicate the change to the stakeholders.. and you need to make sure your columns always match, then the way I would solve this is to connect to the database, get a schema dump of the table and save that as your name translation table, then you can use that array to auto-assign the column headings in your output. It's a fairly robust solution but you'll have to trim some crud off the start of the schema results to build your translation array. – DDeMartini Dec 11 '17 at 21:52
  • Any example you can post..? Sorry, it was stupid but my age in PHP is just 1 day – Pro-n-apps Dec 11 '17 at 21:55
  • Sure thing. More of a question of using the SQL to help you out.. I'll come up with something and post it as an answer in a little bit. – DDeMartini Dec 11 '17 at 21:59

3 Answers3

1

More global approach is to use double foreaches

 $data_rows=array();
    foreach ($data as $u ) {
        $row = array();
        foreach ($u as $field)
            {
            $row[] = $field; // collect dynamic row fields

            }
    $data_rows[] = $row;  // each row will have own array of fields
    }

/// EDITED

public function generate_csv($table) // better to have table name here
{
 $data_rows = array();
    $data_rows = array();
    global $wpdb, $bp;
    $sql = "SELECT * FROM " . $table . "";

    $data= $wpdb->get_results($sql);    
    $fh = @fopen( 'php://output', 'w' );


    //following the example from: https://stackoverflow.com/a/31068464/1171074
    $header_data=array(); 
    foreach ( $wpdb->get_col( "DESC " . $table, 0 ) as $column_name ) {
        $header_data[] = $column_name; 
    }

    array_push($data_rows,$header_data); // first array will be columns names

     foreach ($data as $u ) {
        $row = array();
        foreach ($u as $field)
            {
            $row[] = $field; // collect dynamic row fields

            }
    $data_rows[] = $row;  // each row will have own array of fields
    }

    ............  // rest of the code

    }
Sergiu Costas
  • 530
  • 4
  • 8
  • 26
1

You can use the virtual INFORMATION_SCHEMA.COLUMNS table to get the column names, like so:

"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = {$table}"

0

This should get you pretty close, if not all the way there. It will query the table, build a headers row for the csv, then it will assemble each data row. You shouldn't need to know the row name, if you iterate the response row as value..

I apologize up front if it's a little buggy, since I don't have a PHP box handy where I'm at to verify the precise syntax.

public function generate_csv() {

    global $wpdb;
    global $bp;
    $headers   = array();
    $data_rows = array();
    $table     = 'ProductDetails';
    $data_rows = array();
    $header_row;

    # determine table field names
    $table_sql = sprintf("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '%s'",$table);

    # this will run the query and stuff field names into
    $resp = $wpdb->get_results($table_sql);
    foreach($resp as $row){
        array_push($headers,$row[0]);
    }

    # get the records from the datbase
    $data= $wpdb->get_results(sprintf("SELECT * FROM %s",$table));

    # open output handle
    $fh = @fopen( 'php://output', 'w' );

    foreach ($data as $record ) {
       $row = array();
       foreach($record as $value){
           array_push($row,$value);
       }
       array_push($data_rows,$row);
    }
    header("Pragma: public");
      ... Some more header ...
    header("Content-Transfer-Encoding: binary");

    fputcsv( $fh, $headers );
    foreach ( $data_rows as $data_row ) {
        fputcsv( $fh, $data_row );
    }
    fclose( $fh );
    return;
 }
DDeMartini
  • 339
  • 1
  • 6
  • It throws an error Warning: Invalid argument supplied for foreach() in C:\some path\plugins\Export\Export.php on line 101
    and line 101 is foreach($wpdb->get_results($sql) as $colname) { array_push($headers,$colname); }
    – Pro-n-apps Dec 11 '17 at 22:26
  • It should treat the response as an array.... or I might have pulled the wrong query to array method.. I'll edit it when I have a change to make a full test case for it. – DDeMartini Dec 11 '17 at 22:38
  • Let us know once u come up with op.. Thanks though – Pro-n-apps Dec 11 '17 at 22:49
  • OK, I see, the wpdb is a WordPress specific module, and it seems to differ from the one I'm most used to using. I'm editing the answer now. – DDeMartini Dec 11 '17 at 22:53
  • Fatal error: Cannot use object of type stdClass as array in C:\somePath\plugins\Export\Export.php on line 102 – Pro-n-apps Dec 11 '17 at 23:00