Difference between #103 and #110 of
Yii v2 snippet guide III

Changes

Title unchanged

Yii v2 snippet guide III

Category unchanged

Tutorials

Yii version unchanged

2.0

Tags unchanged

tutorial,yii2,beginer

Content changed

[...]
Note3: There are preinstalled applications in Windows 10 named:
- "ODBC Data Sources 32-bit"
- "ODBC Data Sources 64-bit"
- (Just hit the Win-key and type "ODBC")

Open the one you need, go to tab "System DSN" and click "Add". You will see what drivers are available
. - **only these drivers can be used in the DSN String!!**
 
 
If only "SQL Server" is present, then you need to install the Access Engine (or MS Access) with drivers for your platform. You need driver named cca "Microsoft Access Driver (\*.mdb, \*.accdb)"
 
 
In my case the Engine added following 64bit drivers:
 
- Microsoft Access dBASE Driver (\*.dbf, \*.ndx, \*.mdx)
 
- Microsoft Access Driver (\*.mdb, \*.accdb)
 
- Microsoft Access Text Driver (\*.txt, \*.csv)
 
- Microsoft Excel Driver (\*.xls, \*.xlsx, \*.xlsm, \*.xlsb)
 
 
**And how about Linux ?**
 
 
You need the MS Access Drivers as well, but Microsoft does not provide them. There are some 3rd party [MdbTools](https://github.com/mdbtools/mdbtools) or [EasySoft](https://www.easysoft.com/products/data_access/odbc-access-driver/index.html#section=tab-1), but their are either not-perfect or expensive. Plus there is [Unix ODBC](http://www.unixodbc.org/). 
 
 
For Java there are [Java JDBC](http://www.hxtt.com/access.html), [Jackcess](https://jackcess.sourceforge.io/) and [Ucanaccess](http://ucanaccess.sourceforge.net/site.html).
 
 
**And how about Docker ?**
 
As far as I know you cannot run Windows images under Linux so you will not be able to use the ODBC-advantage of Windows in this case.
 
You can use Linux images under Windows, but I think there is no way how to access the ODBC drivers from virtual Linux. You would have to try it, I haven't tested it yet.
 
 
**Migration batch insert csv**
 
---
 
 
If you want to import CSV into your DB in Yii2 migrations, you can create this "migration base class" and use it as a parent of your actual migration. Then you can use method batchInsertCsv().
 
 
```php
 
<?php
 
 
namespace app\components;
 
 
use yii\db\Migration;
 
 
class BaseMigration extends Migration
 
{
 
    /**
 
     * @param $filename Example: DIR_ROOT . DIRECTORY_SEPARATOR . "file.csv"
 
     * @param $table The target table name
 
     * @param $csvToSqlColMapping [csvColName => sqlColName] (if $containsHeaderRow = true) or [csvColIndex => sqlColName] (if $containsHeaderRow = false)
 
     * @param bool $containsHeaderRow If the header with CSV col names is present
 
     * @param int $batchSize How many rows will be inserted in each batch
 
     * @throws Exception
 
     */
 
    public function batchInsertCsv($filename, $table, $csvToSqlColMapping, $containsHeaderRow = false, $batchSize = 10000, $separator = ';')
 
    {
 
        if (!file_exists($filename)) {
 
            throw new \Exception("File " . $filename . " not found");
 
        }
 
 
        // If you see number 1 in first inserted row and column, most likely BOM causes this.
 
        // Some Textfiles begin with 239 187 191 (EF BB BF in hex)
 
        // bite order mark https://en.wikipedia.org/wiki/Byte_order_mark
 
        // Let's trim it on the first row.
 
        $bom = pack('H*', 'EFBBBF');
 
 
        $handle = fopen($filename, "r");
 
        $lineNumber = 1;
 
        $header = [];
 
        $rows = [];
 
        $sqlColNames = array_values($csvToSqlColMapping);
 
        $batch = 0;
 
 
        if ($containsHeaderRow) {
 
            if (($raw_string = fgets($handle)) !== false) {
 
                $header = str_getcsv(trim($raw_string, $bom), $separator);
 
            }
 
        }
 
 
        // Iterate over every line of the file
 
        while (($raw_string = fgets($handle)) !== false) {
 
            $dataArray = str_getcsv(trim($raw_string, $bom), $separator);
 
 
            if ($containsHeaderRow) {
 
                $dataArray = array_combine($header, $dataArray);
 
            }
 
 
            $tmp = [];
 
            foreach ($csvToSqlColMapping as $csvCol => $sqlCol) {
 
                $tmp[] = trim($dataArray[$csvCol]);
 
            }
 
            $rows[] = $tmp;
 
 
            $lineNumber++;
 
            $batch++;
 
 
            if ($batch >= $batchSize) {
 
                $this->batchInsert($table, $sqlColNames, $rows);
 
                $rows = [];
 
                $batch = 0;
 
            }
 
        }
 
        fclose($handle);
 
 
        $this->batchInsert($table, $sqlColNames, $rows);
 
    }
 
}
 
```
 
8 0
4 followers
Viewed: 191 438 times
Version: 2.0
Category: Tutorials
Written by: rackycz
Last updated by: rackycz
Created on: Jan 21, 2021
Last updated: a year ago
Update Article

Revisions

View all history