CakePHP LogoI often use phpMyAdmin to import csv data into projects I am building, this can be tedious as phpMyAdmin requires the number of fields and field order to match exactly for the csv import to work.

This frustration prompted me to explore the Utils plugin by CakeDC which contains a CsvImport behavior. I wanted this functionality for all of my controllers/models during the development process. Import functionality will eventually end up under the admin interface of my project. If you use admin routing and would like the import functionality only available through an admin url simply change the method name below to admin_import().

Install the CakeDC Utils plugin

Using git, clone the Utils Plugin Repo and checkout the 2.0 branch.

sudo git clone https://github.com/CakeDC/utils.git app/Plugin/Utils
cd app/Plugin/Utils
sudo git checkout 2.0

Enable the Utils plugin

Add the following line to app/Config/bootstrap.php to enable the plugin.

CakePlugin::load('Utils');

Enable the CsvImport behavior in AppModel

Add the following code to app/Model/AppModel.php. If you only want csv import capability for a specific controller, add it there.

public $actsAs = array(
    'Utils.CsvImport' => array(
        'delimiter'  => ','
    )
);

Create a shared View called Common

Create the directory app/View/Common and add the shared import.ctp view

    
mkdir app/View/Common
touch app/View/Common/import.csv

Import <?php echo Inflector::pluralize($modelClass);?> from CSV data file

<?php echo $this->Form->create($modelClass, array('action' => 'import', 'type' => 'file') ); echo $this->Form->input('CsvFile', array('label'=>'','type'=>'file') ); echo $this->Form->end('Submit'); ?>

Add the import action to AppController

Paste the following code into app/Controller/AppController.php.

/**
* CSV Import functionality for all controllers
*     
*/
function import() {
    $modelClass = $this->modelClass;
    if ( $this->request->is('POST') ) {
        $records_count = $this->$modelClass->find( 'count' );
        try {
            $this->$modelClass->importCSV( $this->request->data[$modelClass]['CsvFile']['tmp_name']  );
        } catch (Exception $e) {
            $import_errors = $this->$modelClass->getImportErrors();
            $this->set( 'import_errors', $import_errors );
            $this->Session->setFlash( __('Error Importing') . ' ' . $this->request->data[$modelClass]['CsvFile']['name'] . ', ' . __('column name mismatch.')  );
            $this->redirect( array('action'=>'import') );
        }
        
        $new_records_count = $this->$modelClass->find( 'count' ) - $records_count;
        $this->Session->setFlash(__('Successfully imported') . ' ' . $new_records_count .  ' records from ' . $this->request->data[$modelClass]['CsvFile']['name'] );
        $this->redirect( array('action'=>'index') );
    }
    $this->set('modelClass', $modelClass );
    $this->render('../Common/import');
} //end import()

Add an Import link to the Scaffolding View

If you are using scaffoling in your project and would like to add a link to the
import view, copy lib/Cake/View/Scaffold/index.ctp to app/View/Scaffold/index.ctp
and add the following after line 98.

echo "<li>" . $this->Html->link(
    __d('cake', 'New %s', Inflector::humanize(Inflector::underscore($_alias))),
    array('controller' => $_details['controller'], 'action' => 'add')
) . "</li>";

If you choose not to customize the scaffolding view then you can point your browser directly to the controller action, http://domain.com/controller_name/import

 

Keywords:

  • cakephp csv import
  • cakephp import csv
  • uploading and importing csv to mysql with cakephp