0

I am using the csvUpload behavior of the Utils plugin by CakeDC, on a CakePHP 2.2.1 install.

I have it working great it's processing a rather large csv successfully. However there are two fields in my table / Model that would be considered fixed, as they are based on ID's from from associated models that are not consistent. So I need to get these fixed values via variables which is easy enough.

So my question is, how do I use the fixed fields aspect of csvUpload? I have tried that following and many little variation, which obviously didn't work.

public function upload_csv($Id = null) {
    $unique_add = 69;
    if ( $this->request->is('POST') ) {
        $records_count = $this->Model->find( 'count' );
        try {
            $fixed = array('Model' => array('random_id' => $Id, 'unique_add' => $unique_add));
            $this->Model->importCSV($this->request->data['Model']['CsvFile']['tmp_name'], $fixed);
        } catch (Exception $e) {
            $import_errors = $this->Model->getImportErrors();
            $this->set( 'import_errors', $import_errors );
            $this->Session->setFlash( __('Error Importing') . ' ' . $this->request->data['Model']['CsvFile']['name'] . ', ' . __('column name mismatch.')  );
            $this->redirect( array('action'=>'import') );
        }

        $new_records_count = $this->Model->find( 'count' ) - $records_count;
        $this->Session->setFlash(__('Successfully imported') . ' ' . $new_records_count .  ' records from ' . $this->request->data['Model']['CsvFile']['name'] );
        $this->redirect(array('plugin'=>'usermgmt', 'controller'=>'users', 'action'=>'dashboard'));
    }
}

Any help would be greatly appreciated as I have only found 1 post concerning this behavior when I searching...

Shawn Zelmer
  • 35
  • 1
  • 8

2 Answers2

2

I made my custom method to achieve the same task. Define the following method in app\Plugin\Utils\Model\Behavior

public function getCSVData(Model &$Model, $file, $fixed = array())
{
    $settings = array(
              'delimiter' => ',',
              'enclosure' => '"',
              'hasHeader' => true
            );
    $this->setup($Model, $settings);
    $handle = new SplFileObject($file, 'rb');       
    $header = $this->_getHeader($Model, $handle);
    $db = $Model->getDataSource();
    $db->begin($Model);
    $saved = array();
    $data = array();
    $i = 0;
    while (($row = $this->_getCSVLine($Model, $handle)) !== false)
    {
        foreach ($header as $k => $col)
        {
            // get the data field from Model.field              
            $col = str_replace('.', '-', trim($col));
            if (strpos($col, '.') !== false)
            {
                list($model,$field) = explode('.', $col);
                $data[$i][$model][$field] = (isset($row[$k])) ? $row[$k] : '';
            }
            else
            {
                $col = str_replace(' ','_', $col);
                $data[$i][$Model->alias][$col] = (isset($row[$k])) ? $row[$k] : '';
            }
        }
        $is_valid_row = false;

        foreach($data[$i][$Model->alias] as $col => $value )
        {
            if(!empty($data[$i][$Model->alias][$col]))
            {
                $is_valid_row = true;                   
            }
        }
        if($is_valid_row == true)
        {
            $i++;
            $data = Set::merge($data, $fixed);  
        }
        else
        {
            unset($data[$i]);
        }
    }
    return $data;
}   

And you can use it using:

  $csv_data = $this->Model->getCSVData($this->request->data['Model']['CsvFile']['tmp_name'], $fixed);

Here $csv_data will contain an array of all of those records from the csv file which are not empty and with the fixed field in each record index.

Arun Jain
  • 5,476
  • 2
  • 31
  • 52
  • Thx Arun, but I got it. I was making stupid little mistakes and looking at the big picture for a solution, rather than what was right in front of me. I am about to answer my own question... – Shawn Zelmer Sep 05 '12 at 11:30
  • Hey Arun... Just so you know I did have it working but I didn't like the control I had. So I implemented your solution which is working like a charm. However it's strange, I have conditionals setup to check the field prior to save. I would like a NULL value entered if the fields is blank in the CSV. This won't work. On string values I have to use a fake 'NULL' and on the int fields I have to use a value of 0. The it gets even weirder. My email field won't even accept the fake 'NULL'. I have to format that like an email 'unknown@email.com' for it work... Any ideas??? – Shawn Zelmer Sep 14 '12 at 16:21
  • It did this in the original version I was using as well. This is my first time playing with a CSV upload so is what I explained just something standard that happens with CSV's??? – Shawn Zelmer Sep 14 '12 at 16:23
0

So as I was telling Arun, I answered my own question and figured it out. I was looking to broad instead of really examining what was in front of me. I started running some debugging and figured it out.

First of all, $unique_add = 69 is seen as an int, duh. In order for it to be added to the csv it need to viewed as a string. So it simply becomes, $unique_add = '69'.

I couldn't enter the value of $Id directly into the fixed array. So I just had to perform a simple find to get the value I needed.

$needed_id = $this->Model->find('first', array(
            'condition'=>array('Model.id'=>$Id)
        )
    );

    $random_id = $needed_id['Model']['id'];

Hopefully this won't be needed to help anyone because hopefully no one else will make this silly mistake. But one plus... Now there's actually more than one post on the internet documenting the use of fixed fields in the CakeDC Utils plugin.

Shawn Zelmer
  • 35
  • 1
  • 8