0

I have an issue with my code This script writes the variable to a csv file. I m getting the parameter trough via HTTP GET, the problem is each records comes one by one very slowly. It should be able to take a batch of thousands of records. I also noticed it's incomplete because it's missing about half the record when comparing to the full report downloaded from my vendor. Here is the script:

<?php

error_reporting(E_ALL ^ E_NOTICE);

// setting the default timezone to use.
date_default_timezone_set('America/New_York');

//setting a the CSV File
$fileDate = date("m_d_Y");
$filename = "./csv_archive/" . $fileDate . "_SmsReport.csv";

//Creating handle
$handle = fopen($filename, "a");
//$handle = fopen($directory.$filename, 'a')
//These are the main data field
$item1 = $_REQUEST['item1'];
$item2 = $_REQUEST['item2'];
$item3 = $_REQUEST['item3'];

$mydate = date("Y-m-d H:i:s");

$csvRow = $item2 . "," . $item1 . "," . $item3 . "," . $mydate . "\n";
//writing to csv file
// just making sure the function could wrtite to it
if (!$handle = fopen($filename, 'a')) {
    echo "Cannot open file ($filename)";
    exit;
}
//writing the data 
if (fwrite($handle, $csvRow) === FALSE) {
    echo "Cannot write to file ($filename)";
    exit;
}
fclose($handle);
?>

I rewrote it twice but the issue still persist. This goes beyond the scope of my knowledge so I am hoping someone tell me a better approach. My boss blaming PHP, help me prove him wrong!

4

3 回答 3

0

当请求从 BulkSMS 进入您的服务器时,每个请求都试图打开并写入同一个文件。

这些请求没有排队,并且在开始另一个请求之前不要等待前一个完成,这意味着许多将失败,因为服务器发现文件已被前一个请求使用。

对于此应用程序,最好将每个请求的数据存储在 SQLite 等数据库中,并编写单独的脚本来按需生成 CSV 文件。

我对 SQLite 不是特别熟悉,但我知道它很容易实现并且似乎有据可查

于 2013-02-08T01:05:07.030 回答
0

因为多个请求将同时到达,并发请求将尝试访问同一个输出文件并阻止其他请求访问。

正如我在评论中指出的那样,您应该使用一个不错的数据库。PostgreSQL 或 MySQL 是开源数据库,对 PHP 有很好的支持。

以我的经验,PostgreSQL 是一个更可靠的数据库,并且在许多同时用户的情况下表现更好(尤其是在“写入”数据库时),虽然更难学习(它更“严格”)。

MySQL 更容易学习并且可能就足够了,具体取决于请求/流量的总数。

PostgreSQL: http ://www.postgresql.org

MySQL: http ://www.mysql.com

不要为此使用SQLite 作为数据库,因为 SQLite 是一个基于文件的数据库,设计为单用户数据库,不用于客户端/服务器目的。尝试同时将其用于多个请求会给您带来当前遇到的相同类型的问题

http://www.sqlite.org/whentouse.html SQLite 的可扩展性如何?

于 2013-02-08T07:34:47.360 回答
0

我认为有更好的方法来做到这一点。尝试先将所有数据放入一个数组中,CSV 文件中的每一行本身就是一个数组,然后将其输出。这是我不久前写的一些代码的示例:

class CSV_Output {

    public $data = array();
    public $deliminator;

    function __construct($data, $deliminator=",") {
        if (!is_array($data)) {
            throw new Exception('CSV_Output only accepts data as arrays');
        }
        $this->data = $data;
        $this->deliminator = $deliminator;
    }

    public function output() {
        foreach ($this->data as $row) {
            $quoted_data = array_map(array('CSV_Output', 'add_quotes'), $row);
            echo sprintf("%s\n", implode($this->deliminator, $quoted_data));
        }
    }

    public function headers($name) {
        header('Content-Type: application/csv');
        header("Content-disposition: attachment; filename={$name}.csv");
    }

    private function add_quotes($data) {
        $data = preg_replace('/"(.+)"/', '""$1""', $data);
        return sprintf('"%s"', $data);
    }

}   

// CONSTRUCT OUTPUT ARRAY
$CSV_Data = array(array(
    "Item 1",
    "Item 2",
    "ITem 3",
    "Date"
));

// Needs to loop through all your data..
for($i = 1; $i < (ARGUMENT_TO_STOP_LOOP) ; $i++) {

    $CSV_Data[] = array($_REQUEST['item1'], $_REQUEST['item2'], $_REQUEST['item3'], $_REQUEST['itemdate']);

}

$b = new CSV_Output($CSV_Data);
$b->output();
$b->headers("NAME_YOUR_FILE_HERE");
于 2013-02-08T00:01:30.003 回答