Codeigniter CSV上传然后爆炸

时间:2013-04-04 20:02:34

标签: codeigniter activerecord

我有一些代码可以将CSV文件上传到指定的文件夹,但它不会更新数据库。

public function do_upload()
{
    $csv_path = realpath(APPPATH . '/../assets/uploads/CSV/');
    $config['upload_path']   = $csv_path;
    $config['allowed_types'] = '*'; // All types of files allowed
    $config['overwrite']     = true; // Overwrites the existing file

    $this->upload->initialize($config);
    $this->load->library('upload', $config);

    if ( ! $this->upload->do_upload('userfile'))
    {
        $error = array('error' => $this->upload->display_errors());

        $this->layout->buffer('content', 'program/upload', $error);
        $this->layout->render();
    }
    else
    {


        $image_data = $this->upload->data();
        $fname = $image_data['file_name'];
        $fpath = $image_data['file_path'].$fname;
        $fh = fopen($fpath, "r");



        $insert_str = 'INSERT INTO wc_program (JobRef, Area, Parish, AbbrWorkType, WorkType, Timing, TrafficManagement, Location, Duration, Start, Finish) VALUES '."\n";


        if ($fh) {

            // Create each set of values.
            while (($csv_row = fgetcsv($fh, 2000, ',')) !== false) {

                foreach ($csv_row as &$row) {
                    $row = strtr($row, array("'" => "\'", '"' => '\"'));
                }

                $insert_str .= '("'
                    // Implode the array and fix pesky apostrophes.
                    .implode('","', $csv_row)
                    .'"),'."\n";
            }

            // Remove the trailing comma.
            $insert_str = rtrim($insert_str, ",\n");

            // Insert all of the values at once.
            $this->db->set($insert_str);

            echo '<script type="text/javascript">
                        alert("Document successfully uploaded and saved to the database.");
                        location = "program/index";
                </script>';
        } 
        else {
                echo '<script type="text/javascript">
                        alert("Sorry! Something went wrong please proceed to try again.");
                        location = "program/upload";
                </script>';
        } 


    }
}

当我运行var_dump($ fh)时;它显示:类型(流)的资源(89)

当我运行var_dump($fpath)时,会显示:string(66) "/Applications/MAMP/htdocs/site/assets/uploads/CSV/wc_program.csv"

所以这一切都上传但是它没有更新数据库有什么问题? 我已经尝试了各种更改fopen方法,但仍然没有快乐,我真的需要它添加到数据库,插入查询和设置查询应该做的但不是。

任何帮助都非常感谢!

1 个答案:

答案 0 :(得分:1)

您没有在数据库上运行任何查询。您正在将活动记录语法与简单查询语法混合使用。活动记录插入查询将通过调用来执行。

$this->db->insert('my_table');

db::set()实际上并不查询数据库。它会接收在db::insert()db::update()被调用后插入或更新的键/值对。如果您自己构建查询,则需要使用db::query()函数。

查看active directory documentation

您可以使用$this->db->query('put your query here'),但是您失去了CodeIgniter内置安全性的好处。查看CodeIgniter's query个功能。

我将举例说明使用CodeIgniter插入数据库的众多方法中的几种。这些示例将根据您的评论生成查询。您需要相应地调整代码。

示例1

$result = $this->db
    ->set('JobRef', 911847)
    ->set('Area', 'Coastal')
    ->set('Parish', 'Yapton')
    ->set('AbbrWorkType', 'Micro')
    ->set('WorkType', 'Micro-Asphalt Surfacing')
    ->set('Timing', 'TBC')
    ->set('TrafficManagement', 'No Positive Traffic Management')
    ->set('Location', 'Canal Road (added PMI 16/07/12)')
    ->set('Duration', '2 days')
    ->set('Start', '0000-00-00')
    ->set('Finish', '0000-00-00') 
    ->insert('wc_program');

echo $this->db->last_query() . "\n\n";
echo "RESULT: \n\n";
print_r($result);

示例2 (使用关联数组):

$row = array(
    'JobRef' => 911847,
    'Area' => 'Coastal',
    'Parish' => 'Yapton',
    'AbbrWorkType' => 'Micro',
    'WorkType' => 'Micro-Asphalt Surfacing',
    'Timing' => 'TBC',
    'TrafficManagement' => 'No Positive Traffic Management',
    'Location' => 'Canal Road (added PMI 16/07/12)',
    'Duration' => '2 days',
    'Start' => '0000-00-00',
    'Finish' => '0000-00-00'
);
$this->db->insert('wc_program', $row);
// This will do the same thing
// $this->db->set($row);
// $this->db->insert('wc_program');
echo $this->db->last_query();

示例1和2正在使用Active Record。信息将逐个存储,然后在您进行最终调用时构建查询。这有几个优点。它允许您动态构建查询,而无需担心SQL语法和关键字的顺序。它也逃脱了你的数据。

示例3 (简单查询):

$query = 'INSERT INTO 
    wc_program 
        (JobRef, Area, Parish, AbbrWorkType, WorkType, Timing, TrafficManagement, Location, Duration, Start, Finish) 
    VALUES 
        ("911847","Coastal","Yapton","Micro","Micro-Asphalt Surfacing","TBC","No Positive Traffic Management","Canal Road (added PMI 16/07/12)","2 days","0000-00-00","0000-00-00")';
$result = $this->db->query($query);
echo $this->db->last_query() . "\n\n";
echo "RESULT: \n";
print_r($result);

通过这种方式可以防止注射,可能导致更多错误,并且更难以更改/维护。

如果你打算这样做,你应该使用以下语法,这将防止注入。

示例4

$query = 'INSERT INTO 
    wc_program 
        (JobRef, Area, Parish, AbbrWorkType, WorkType, Timing, TrafficManagement, Location, Duration, Start, Finish) 
    VALUES 
        (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);';

$row = array(
    911847,
    'Coastal',
    'Yapton',
    'Micro',
    'Micro-Asphalt Surfacing',
    'TBC',
    'No Positive Traffic Management',
    'Canal Road (added PMI 16/07/12)',
    '2 days',
    '0000-00-00',
    '0000-00-00'
);

$result = $this->db->query($query, $row);
echo $this->db->last_query() . "\n\n";
echo "RESULT: \n";
print_r($result);

CodeIgniter会替换每个“?”在查询中,在转义后使用数组中的相应值。您可以使用它来运行多个具有相同形式的查询,但只需更新$row数组并从CI的内置安全性中受益,就可以拥有不同的数据。