PHP / MySQLi函数,从3个表生成CSV,但需要单独生成一行

问题描述:

This is my final task on this project and unsure how I can adjust for what I need. I am new to all this, so rather happy I've got this far!

The following function gets data from 3 tables and generates a CSV file (great and works fine) however it splits the file up in 3 sections and ideally I would like all data per order per line.

As it stands, you see the 3 tables in 3 sections but I really need all data from the invoice id within 1 line.

Code:

// download invoice csv sheet
if ($action == 'download_csv'){

    header("Content-type: text/csv"); 

    // output any connection error
    if ($mysqli->connect_error) {
        die('Error : ('.$mysqli->connect_errno .') '. $mysqli->connect_error);
    }

    $tables = array('invoices', 'customers', 'invoice_items'); // array of tables need to export

    $file_name = 'invoice-export-'.date('d-m-Y').'.csv';   // file name
    $file_path = 'downloads/'.$file_name; // file path

    $file = fopen($file_path, "w"); // open a file in write mode
    chmod($file_path, 0777);    // set the file permission

    // loop for tables
    foreach($tables as $table) {
        $table_column = array();
        $query_table_columns = "SHOW COLUMNS FROM $table";

        // fetch table field names
        if ($result_column = mysqli_query($mysqli, $query_table_columns)) {
            while ($column = $result_column->fetch_row()) {
                $table_column[] = $column[0];
            }
        }

        // Format array as CSV and write to file pointer
        fputcsv($file, $table_column, ",", '"');

        $query_table_columns_data = "SELECT * FROM $table";

        if ($result_column_data = mysqli_query($mysqli, $query_table_columns_data)) {

            // fetch table fields data
            while ($column_data = $result_column_data->fetch_row()) {
                $table_column_data = array();
                foreach($column_data as $data) {
                    $table_column_data[] = $data;
                }

                // Format array as CSV and write to file pointer
                fputcsv($file, $table_column_data, ",", '"');
            }

        }
    }

    //if saving success
    if ($result_column_data = mysqli_query($mysqli, $query_table_columns_data)) {
        echo json_encode(array(
            'status' => 'Success',
            'message'=> 'CSV has been generated and is available in the /downloads folder for future reference, you can download by <a href="/downloads/'.$file_name.'">clicking here</a>.'
        ));

    } else {
        //if unable to create new record
        echo json_encode(array(
            'status' => 'Error',
            //'message'=> 'There has been an error, please try again.'
            'message' => 'There has been an error, please try again.<pre>'.$mysqli->error.'</pre><pre>'.$query.'</pre>'
        ));
    }


    // close file pointer
    fclose($file);

    $mysqli->close();

}

Assuming invoice is unique in the invoices table and the customers table, and that contains the common value we use to "match" rows in all of the tables...

(A quick note here: this is where actual table definitions, including PRIMARY KEYs, UNIQUE KEYs, FOREIGN KEYs, datatypes of columns, and even column comments, would be invaluable in aiding communication, and us not having to make possibly erroneous assumptions...)

Here's an example of the SQL query you would need to "combine" the rows from all of the tables, one row per invoice_item

SELECT i.id
     , i.invoice
     , i.foo
     , i.bar

     , c.id        AS c_id
     , c.invoice   AS c_invoice
     , c.name      AS c_name
  -- , c.fee
  -- , c.fi

     , t.id        AS t_id
     , t.invoice   AS t_invoice
     , t.product   AS t_product
     , t.qty       AS t_qty
  -- , t.fo
  -- , t.fum       

  FROM invoice i
  LEFT
  JOIN customer c
    ON c.invoice = i.invoice
  LEFT
  JOIN invoice_item t
    ON t.invoice = i.invoice
 ORDER
    BY i.id
     , c.id
     , t.id

Add whatever columns from each table you need, and make sure each column has a unique name in the returned row (using an AS column_alias after each expression in the SELECT list.)