├── .gitignore ├── LICENSE ├── README.md ├── TODO.md ├── composer.json ├── phpunit.xml ├── src ├── AccessServiceProvider.php ├── Doctrine │ └── DBAL │ │ ├── Driver │ │ └── Access │ │ │ ├── AccessConnection.php │ │ │ ├── AccessStatement.php │ │ │ └── Driver.php │ │ ├── Platforms │ │ ├── AccessPlatform.php │ │ └── Keywords │ │ │ └── AccessKeywords.php │ │ └── Schema │ │ └── AccessSchemaManager.php └── Illuminate │ └── Database │ ├── AccessConnection.php │ ├── Query │ ├── Grammars │ │ └── AccessGrammar.php │ └── Processors │ │ └── AccessProcessor.php │ └── Schema │ └── Grammars │ └── AccessGrammar.php └── tests └── .gitkeep /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac DS_Store Files 2 | .DS_Store 3 | 4 | # windows thumbnail cache 5 | Thumbs.db 6 | 7 | # composer vendor dir 8 | /vendor 9 | composer.lock 10 | 11 | # phpstorm project files 12 | .idea 13 | .phpstorm.meta.php 14 | 15 | # netbeans project files 16 | nbproject/* 17 | 18 | # zend studio for eclipse project files 19 | .buildpath 20 | .project 21 | .settings 22 | 23 | # PHPUnit 24 | report/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Zoilo Mora 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This repository is no longer maintained. 2 | 3 | # It is recommended to visit the updated repository https://github.com/zoilomora/doctrine-dbal-msaccess that is being maintained and is not limited to the Laravel framework. 4 | 5 | # Laravel ORM for Microsoft Access DB 6 | [![Latest Stable Version](https://poser.pugx.org/zoilomora/laravel-msaccess/v/stable)](https://packagist.org/packages/zoilomora/laravel-msaccess) 7 | [![Total Downloads](https://poser.pugx.org/zoilomora/laravel-msaccess/downloads)](https://packagist.org/packages/zoilomora/laravel-msaccess) 8 | [![Latest Unstable Version](https://poser.pugx.org/zoilomora/laravel-msaccess/v/unstable)](https://packagist.org/packages/zoilomora/laravel-msaccess) 9 | [![License](https://poser.pugx.org/zoilomora/laravel-msaccess/license)](https://packagist.org/packages/zoilomora/laravel-msaccess) 10 | [![composer.lock](https://poser.pugx.org/zoilomora/laravel-msaccess/composerlock)](https://packagist.org/packages/zoilomora/laravel-msaccess) 11 | 12 | This package helps you to manage **Microsoft Access DB** by **ODBC Connection** 13 | with the integrated [Laravel](https://github.com/laravel/laravel) ORM. 14 | 15 | ## Installation 16 | 1) Install via composer 17 | ``` 18 | composer require zoilomora/laravel-msaccess 19 | ``` 20 | 21 | 2) Add Service Provider to `config/app.php` in `providers` section: 22 | ```php 23 | \ZoiloMora\AccessServiceProvider::class, 24 | ``` 25 | 26 | 3) Create a **DSN** with the connection to the database. 27 | 28 | 4) Add connection to `config/database.php` in `connections` section: 29 | ```php 30 | 'access' => [ 31 | 'driver' => 'pdo_access', 32 | 'connection_string' => 'dsn={namedsn}', 33 | 'username' => '', 34 | 'password' => '', 35 | 'table_prefix' => '', 36 | ] 37 | ``` 38 | 39 | 5) Replace `{namedsn}` with the **name of DSN**. 40 | 41 | ## Connect model with the connection 42 | 1) In the model class add the `$connection` variable like this: 43 | ```php 44 | protected $connection = 'access'; 45 | ``` 46 | 47 | ## License 48 | Licensed under the [MIT license](http://opensource.org/licenses/MIT) 49 | 50 | Read [LICENSE](LICENSE) for more information 51 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | - **Problem with diacritics ([#1](https://github.com/zoilomora/laravel-msaccess/issues/1))**: In a DB in French, the symbols become question marks. 4 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zoilomora/laravel-msaccess", 3 | "description": "This package helps you to manage Microsoft Access DB by ODBC Connection with the integrated Laravel ORM.", 4 | "version": "1.0.0-beta", 5 | "type": "library", 6 | "keywords": [ 7 | "laravel", 8 | "orm", 9 | "microsoft-access" 10 | ], 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Zoilo Mora", 15 | "email": "zoilo.mora@hotmail.com", 16 | "homepage": "http://zoilomora.net", 17 | "role": "Developer" 18 | } 19 | ], 20 | "require": { 21 | "doctrine/dbal": "^2.6", 22 | "illuminate/database": "^5.4" 23 | }, 24 | "require-dev": { 25 | "phpunit/phpunit": "~5.7" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "ZoiloMora\\": "src/" 30 | } 31 | }, 32 | "support": { 33 | "issues": "https://github.com/zoilomora/laravel-msaccess/issues" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./tests 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/AccessServiceProvider.php: -------------------------------------------------------------------------------- 1 | app['db']); 18 | } 19 | 20 | /** 21 | * Register the service provider. 22 | */ 23 | public function register() 24 | { 25 | // Add database driver. 26 | $this->app->resolving('db', function ($db) { 27 | /** @var DatabaseManager $db */ 28 | $db->extend('pdo_access', function ($config, $name) { 29 | $config['name'] = $name; 30 | return new AccessConnection($config); 31 | }); 32 | }); 33 | } 34 | } -------------------------------------------------------------------------------- /src/Doctrine/DBAL/Driver/Access/AccessConnection.php: -------------------------------------------------------------------------------- 1 | setAttribute(\PDO::ATTR_STATEMENT_CLASS, array(AccessStatement::class, array())); 20 | } 21 | 22 | /** 23 | * {@inheritdoc} 24 | */ 25 | public function quote($value, $type = \PDO::PARAM_STR) 26 | { 27 | $val = parent::quote($value, $type); 28 | // Fix for a driver version terminating all values with null byte 29 | if (strpos($val, "\0") !== false) { 30 | $val = substr($val, 0, -1); 31 | } 32 | return $val; 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | */ 38 | public function beginTransaction() 39 | { 40 | if ($this->_pdoTransactionsSupported() === true) { 41 | parent::beginTransaction(); 42 | } else { 43 | $this->exec('BEGIN TRANSACTION'); 44 | } 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function commit() 51 | { 52 | if ($this->_pdoTransactionsSupported() === true) { 53 | parent::commit(); 54 | } else { 55 | $this->exec('COMMIT TRANSACTION'); 56 | } 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | public function rollback() 63 | { 64 | if ($this->_pdoTransactionsSupported() === true) { 65 | parent::rollback(); 66 | } else { 67 | $this->exec('ROLLBACK TRANSACTION'); 68 | } 69 | } 70 | 71 | /** 72 | * Gets support for native transactions 73 | * 74 | * @return bool 75 | */ 76 | private function _pdoTransactionsSupported() 77 | { 78 | if (!is_null($this->_pdoTransactionsSupport)) { 79 | return $this->_pdoTransactionsSupport; 80 | } 81 | 82 | try { 83 | $supported = true; 84 | parent::beginTransaction(); 85 | } catch (\PDOException $e) { 86 | $supported = false; 87 | } 88 | 89 | if ($supported) { 90 | parent::commit(); 91 | } 92 | 93 | return $this->_pdoTransactionsSupport = $supported; 94 | } 95 | } -------------------------------------------------------------------------------- /src/Doctrine/DBAL/Driver/Access/AccessStatement.php: -------------------------------------------------------------------------------- 1 | params = $params; 18 | 19 | return new AccessConnection( 20 | $this->getDsn($params), 21 | $username, 22 | $password, 23 | $driverOptions 24 | ); 25 | } 26 | 27 | /** 28 | * Create a DSN string from a configuration. 29 | * 30 | * @param array $config 31 | * @return string 32 | */ 33 | private function getDsn(array $config) 34 | { 35 | $dsn = trim('odbc:'.$config['connection_string']); 36 | 37 | if(substr($dsn, -1) !== ';') { 38 | $dsn .= ';'; 39 | } 40 | 41 | return $dsn; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function getDatabasePlatform() 48 | { 49 | return new AccessPlatform(); 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function getSchemaManager(\Doctrine\DBAL\Connection $conn) 56 | { 57 | return new AccessSchemaManager($conn); 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | */ 63 | public function getName() 64 | { 65 | return 'pdo_access'; 66 | } 67 | 68 | /** 69 | * {@inheritdoc} 70 | */ 71 | public function getDatabase(\Doctrine\DBAL\Connection $conn) 72 | { 73 | return $this->params['name']; 74 | } 75 | } -------------------------------------------------------------------------------- /src/Doctrine/DBAL/Platforms/AccessPlatform.php: -------------------------------------------------------------------------------- 1 | getDsn($config); 17 | 18 | $pdo = new \ZoiloMora\Doctrine\DBAL\Driver\Access\AccessConnection($dsn); 19 | 20 | parent::__construct($pdo, '', '', $config); 21 | $this->createConnection($pdo); 22 | 23 | if(array_key_exists('table_prefix', $config)) { 24 | $this->setTablePrefix($config['table_prefix']); 25 | } 26 | } 27 | 28 | /** 29 | * Create a DSN string from a configuration. 30 | * 31 | * @param array $config 32 | * @return string 33 | */ 34 | protected function getDsn(array $config) 35 | { 36 | $dsn = trim('odbc:'.$config['connection_string']); 37 | 38 | if(substr($dsn, -1) !== ';') { 39 | $dsn .= ';'; 40 | } 41 | 42 | return $dsn; 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | protected function getDefaultQueryGrammar() 49 | { 50 | return new \ZoiloMora\Illuminate\Database\Query\Grammars\AccessGrammar(); 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | protected function getDefaultPostProcessor() 57 | { 58 | return new \ZoiloMora\Illuminate\Database\Query\Processors\AccessProcessor(); 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | */ 64 | protected function getDefaultSchemaGrammar() 65 | { 66 | return new \ZoiloMora\Illuminate\Database\Schema\Grammars\AccessGrammar(); 67 | } 68 | 69 | /** 70 | * Connection creation 71 | * 72 | * @param \PDO $pdo 73 | */ 74 | protected function createConnection($pdo) 75 | { 76 | $params = [ 77 | 'user' => $this->config['username'], 78 | 'password' => $this->config['password'], 79 | 'pdo' => $pdo, 80 | 'driverClass' => DoctrineDriver::class, 81 | ]; 82 | $this->doctrineConnection = \Doctrine\DBAL\DriverManager::getConnection($params); 83 | } 84 | 85 | /** 86 | * @inheritdoc 87 | */ 88 | public function getDriverName() 89 | { 90 | return 'pdo_access'; 91 | } 92 | 93 | /** 94 | * Get the Doctrine DBAL driver. 95 | * 96 | * @return \ZoiloMora\Doctrine\DBAL\Driver\Access\Driver 97 | */ 98 | protected function getDoctrineDriver() 99 | { 100 | return new DoctrineDriver; 101 | } 102 | } -------------------------------------------------------------------------------- /src/Illuminate/Database/Query/Grammars/AccessGrammar.php: -------------------------------------------------------------------------------- 1 | orders === null) { 38 | $query->orderByRaw('1 asc'); 39 | } 40 | 41 | $sql = parent::compileComponents($query); 42 | 43 | return $sql; 44 | } 45 | 46 | /** 47 | * Compile the "select *" portion of the query. 48 | * 49 | * @param \Illuminate\Database\Query\Builder $query 50 | * @param array $columns 51 | * @return string|null 52 | */ 53 | protected function compileColumns(Builder $query, $columns) 54 | { 55 | if (!is_null($query->aggregate)) { 56 | return; 57 | } 58 | 59 | $select = $query->distinct ? 'select distinct ' : 'select '; 60 | 61 | return $select.$this->compileLimit($query, $query->limit).$this->columnize($columns); 62 | } 63 | 64 | /** 65 | * Compile the "limit" portions of the query. 66 | * 67 | * @param \Illuminate\Database\Query\Builder $query 68 | * @param int $limit 69 | * @return string 70 | */ 71 | protected function compileLimit(Builder $query, $limit) 72 | { 73 | return $limit > 0 ? 'top '.(int) $limit .' ' : ''; 74 | } 75 | } -------------------------------------------------------------------------------- /src/Illuminate/Database/Query/Processors/AccessProcessor.php: -------------------------------------------------------------------------------- 1 |