├── .gitignore ├── .travis.yml ├── composer.json ├── phpunit.xml ├── readme.md ├── src ├── Nwidart │ └── DbExporter │ │ ├── Commands │ │ ├── CopyToRemoteCommand.php │ │ ├── GeneratorCommand.php │ │ ├── MigrationsGeneratorCommand.php │ │ └── SeedGeneratorCommand.php │ │ ├── DbExportHandler.php │ │ ├── DbExportHandlerServiceProvider.php │ │ ├── DbExporter.php │ │ ├── DbMigrations.php │ │ ├── DbMigrationsServiceProvider.php │ │ ├── DbSeeding.php │ │ ├── Exceptions │ │ └── InvalidDatabaseException.php │ │ ├── Server.php │ │ ├── facades │ │ ├── DbExportHandler.php │ │ └── DbMigrations.php │ │ └── templates │ │ ├── migration.txt │ │ └── seed.txt └── config │ └── config.php └── tests └── .gitkeep /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .DS_Store 5 | ### PhpStorm ### 6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 7 | 8 | ## Directory-based project format 9 | .idea/ 10 | # if you remove the above rule, at least ignore user-specific stuff: 11 | # .idea/workspace.xml 12 | # .idea/tasks.xml 13 | # and these sensitive or high-churn files: 14 | # .idea/dataSources.ids 15 | # .idea/dataSources.xml 16 | # .idea/sqlDataSources.xml 17 | # .idea/dynamic.xml 18 | 19 | ## File-based project format 20 | *.ipr 21 | *.iml 22 | *.iws 23 | 24 | ## Additional for IntelliJ 25 | out/ 26 | 27 | # generated by mpeltonen/sbt-idea plugin 28 | .idea_modules/ 29 | 30 | # generated by JIRA plugin 31 | atlassian-ide-plugin.xml 32 | 33 | # generated by Crashlytics plugin (for Android Studio and Intellij) 34 | com_crashlytics_export_strings.xml 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | 8 | before_script: 9 | - curl -s http://getcomposer.org/installer | php 10 | - php composer.phar install --dev 11 | 12 | script: phpunit -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nwidart/db-exporter", 3 | "description": "Export your database quickly and easily as a Laravel Migration and all the data as a Seeder class.", 4 | "keywords": ["Export", "PHP", "Database", "Migrations", "Laravel", "Seed", "Command", "Artisan"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Nicolas Widart", 9 | "email": "n.widart@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=5.3.0", 14 | "illuminate/support": "4.*|5.*" 15 | }, 16 | "autoload": { 17 | "psr-0": { 18 | "Nwidart\\DbExporter": "src/" 19 | } 20 | }, 21 | "minimum-stability": "dev" 22 | } -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/ 16 | 17 | 18 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/nWidart/DbExporter/badges/quality-score.png?s=7bd2e14ca4097b979efa1d0d558c3ae17dd870bf)](https://scrutinizer-ci.com/g/nWidart/DbExporter/) 2 | [![Latest Stable Version](https://poser.pugx.org/nwidart/db-exporter/v/stable.svg)](https://packagist.org/packages/nwidart/db-exporter) [![Total Downloads](https://poser.pugx.org/nwidart/db-exporter/d/total)](https://packagist.org/packages/nwidart/db-exporter) [![Latest Unstable Version](https://poser.pugx.org/nwidart/db-exporter/v/unstable.svg)](https://packagist.org/packages/nwidart/db-exporter) [![License](https://poser.pugx.org/nwidart/db-exporter/license.svg)](https://packagist.org/packages/nwidart/db-exporter) 3 | 4 | # Database Exporter 5 | 6 | Export your database quickly and easily as a Laravel Migration and all the data as a Seeder class. This can be done via artisan commands or a controller action. 7 | 8 | 9 | Please note that I've only tested this package on a **MySQL** database. It has been confirmed it does not work with [Postgres](https://github.com/nWidart/DbExporter/issues/17#issuecomment-56990481). 10 | 11 | ## Installation 12 | 13 | ``` 14 | 15 | $ composer require nwidart/db-exporter 16 | 17 | ``` 18 | 19 | Add the service provider to `app/config/app.php`: 20 | 21 | ```php 22 | 'Nwidart\DbExporter\DbExportHandlerServiceProvider' 23 | ``` 24 | 25 | (Optional) Publish the configuration file. 26 | 27 | ``` 28 | php artisan config:publish nwidart/db-exporter 29 | ``` 30 | 31 | *Use `dev-master` as version requirement to be on the cutting edge* 32 | 33 | 34 | ## Documentation 35 | 36 | ### From the commandline 37 | 38 | #### Export database to migration 39 | 40 | **Basic usage** 41 | 42 | ``` 43 | php artisan dbe:migrations 44 | ``` 45 | 46 | **Specify a database** 47 | 48 | ``` 49 | php artisan dbe:migrations otherDatabaseName 50 | ``` 51 | 52 | **Ignoring tables** 53 | 54 | You can ignore multiple tables by seperating them with a comma. 55 | 56 | ``` 57 | php artisan dbe:migrations --ignore="table1,table2" 58 | ``` 59 | 60 | #### Export database table data to seed class 61 | This command will export all your database table data into a seed class. 62 | 63 | ``` 64 | php artisan dbe:seeds 65 | ``` 66 | *Important: This **requires your database config file to be updated in `app/config/database.php`**.* 67 | 68 | 69 | #### Uploading migrations/seeds to remote server 70 | **Important: This requires your app/config/remote.php to be configured.** 71 | 72 | **Important: The package configuration remote key needs to be configured to correspond to your remotes directory structure.** 73 | 74 | 75 | You can with the following command, upload migrations and / or seeds to a remote host with `php artisan dbe:remote remoteName [--migrations] [--seeds]` 76 | 77 | For instance **to upload the migrations to the production server:** 78 | 79 | ``` 80 | php artisan dbe:remote production --migrations 81 | ``` 82 | Or **upload the seeds to the production server:** 83 | 84 | ``` 85 | php artisan dbe:remote production --seeds 86 | ``` 87 | Or even combine the two: 88 | 89 | ``` 90 | php artisan dbe:remote production --migrations --seeds 91 | ``` 92 | 93 | *** 94 | 95 | ### From a controller / route 96 | 97 | #### Database to migration 98 | 99 | ##### Export current database 100 | 101 | **This requires your database config file to be updated.** The class will export the database name from your `app/config/database.php` file, based on your 'default' option. 102 | 103 | 104 | Make a export route on your development environment 105 | 106 | ```php 107 | 108 | Route::get('export', function() 109 | { 110 | DbExportHandler::migrate(); 111 | }); 112 | ``` 113 | 114 | ##### Export a custom database 115 | 116 | ```php 117 | 118 | Route::get('export', function() 119 | { 120 | DbExportHandler::migrate('otherDatabaseName'); 121 | }); 122 | ``` 123 | 124 | #### Database to seed 125 | 126 | 127 | This will write a seeder class with all the data of the current database. 128 | 129 | ```php 130 | 131 | Route::get('exportSeed', function() 132 | { 133 | DbExportHandler::seed(); 134 | }); 135 | ``` 136 | 137 | Next all you have to do is add the call method on the base seed class: 138 | 139 | ```php 140 | 141 | $this->call('nameOfYourSeedClass'); 142 | 143 | ``` 144 | 145 | Now you can run from the commmand line: 146 | 147 | * `php artisan db:seed`, 148 | * or, without having to add the call method: `php artisan db:seed --class=nameOfYourSeedClass` 149 | 150 | #### Chaining 151 | You can also combine the generation of the migrations & the seed: 152 | 153 | ```php 154 | 155 | DbExportHandler::migrate()->seed(); 156 | 157 | ``` 158 | Or with: 159 | 160 | ```php 161 | 162 | DbExportHandler::migrateAndSeed(); 163 | 164 | ``` 165 | **Important :** Please note you cannot set a external seed database. 166 | If you know of a way to connect to a external DB with laravel without writing in the app/database.php file [let me know](http://www.twitter.com/nicolaswidart). 167 | 168 | 169 | #### Ignoring tables 170 | By default the migrations table is ignored. You can add tabled to ignore with the following syntax: 171 | 172 | ```php 173 | 174 | DbExportHandler::ignore('tableToIgnore')->migrate(); 175 | DbExportHandler::ignore('tableToIgnore')->seed(); 176 | 177 | ``` 178 | You can also pass an array of tables to ignore. 179 | 180 | 181 | 182 | ## TODO 183 | * ~~Export data too. It would be cool if it could also generate a seed file based of the data in the tables. This would be more usefull to run on the production server to get the seed on the development server.~~ **3/1/13** 184 | * ~~Deploy the migration directly to the production server ready to be migrated. (as an option)~~ **5/1/13** 185 | * ~~Make commands to do the same thing (export db to migration)~~ **4/1/13** 186 | * ~~Make commands to do the same thing (export db to seed)~~ **4/1/13** 187 | * Making the upload to remote available directly when generating the migrations/seeds 188 | 189 | 190 | 191 | 192 | ## Credits 193 | Credits to **@michaeljcalkins** for the [original class](http://paste.laravel.com/1jdw#4) on paste.laravel.com (which goal was to generate migrations from a database). Sadly I couldn't get it working as-is, so I debugged it and decided to make a package out of it, and added a couple a features of my own. 194 | 195 | ## License (MIT) 196 | 197 | Copyright (c) 2013 [Nicolas Widart](http://www.nicolaswidart.com) , n.widart@gmail.com 198 | 199 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 200 | 201 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 202 | 203 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 204 | 205 |
206 | 207 | 208 | 209 | 210 |
211 | 212 | -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/Commands/CopyToRemoteCommand.php: -------------------------------------------------------------------------------- 1 | migrationsPath = app_path() . "/database/migrations"; 30 | $this->seedsPath = app_path() . "/database/seeds"; 31 | 32 | $this->server = $server; 33 | } 34 | 35 | public function fire() 36 | { 37 | $succes = $this->handleOptions(); 38 | if ($succes) { 39 | // Inform what files have been uploaded 40 | foreach ($this->uploadedFiles as $type => $files) { 41 | $this->info(ucfirst($type)); 42 | foreach ($files as $file) { 43 | $this->sectionMessage($type, $file .' uploaded.'); 44 | } 45 | } 46 | 47 | $this->blockMessage('Success!', 'Everything uploaded!'); 48 | } 49 | } 50 | 51 | protected function getArguments() 52 | { 53 | return array( 54 | array('remote', InputArgument::REQUIRED, 'The remote name.') 55 | ); 56 | } 57 | 58 | protected function getOptions() 59 | { 60 | return array( 61 | array('migrations', 'mig', InputOption::VALUE_NONE, 'Upload the migrations to the remote host.', null), 62 | array('seeds', 'seed', InputOption::VALUE_NONE, 'Upload the seeds to the remote host.', null) 63 | ); 64 | } 65 | 66 | private function getRemoteName() 67 | { 68 | // Use default production key 69 | if (!$this->argument('remote')) { 70 | return 'production'; 71 | } else { 72 | return $this->argument('remote'); 73 | } 74 | } 75 | 76 | private function handleOptions() 77 | { 78 | $options = $this->option(); 79 | switch ($options) { 80 | case (($options['seeds'] === true) && ($options['migrations'] === true)): 81 | if (!$this->upload('migrations')) return false; 82 | return $this->upload('seeds'); 83 | break; 84 | case $options['migrations'] === true: 85 | // // $this->server->upload('migrations'); 86 | $this->commandOptions = 'migrations'; 87 | return $this->upload('migrations'); 88 | break; 89 | case $options['seeds'] === true: 90 | $this->commandOptions = 'seeds'; 91 | return $this->upload('seeds'); 92 | break; 93 | } 94 | } 95 | 96 | private function upload($what) 97 | { 98 | $localPath = "{$what}Path"; 99 | 100 | $dir = scandir($this->$localPath); 101 | $remotePath = config('db-exporter.remote.'.$what); 102 | 103 | // Prepare the progress bar 104 | $progress = $this->getHelperSet()->get('progress'); 105 | $filesCount = count($dir) - count($this->ignoredFiles); 106 | $progress->start($this->output, $filesCount); 107 | $this->info(ucfirst($what)); 108 | foreach($dir as $file) { 109 | if (in_array($file, $this->ignoredFiles)) { 110 | continue; 111 | } 112 | 113 | // Capture the uploaded files for displaying later 114 | $this->uploadedFiles[$what][] = $remotePath . $file; 115 | 116 | // Copy the files 117 | SSH::into($this->getRemoteName())->put( 118 | $this->$localPath .'/' . $file, 119 | $remotePath . $file 120 | ); 121 | $progress->advance(); 122 | } 123 | $progress->finish(); 124 | 125 | return true; 126 | } 127 | } -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/Commands/GeneratorCommand.php: -------------------------------------------------------------------------------- 1 | getHelperSet()->get('formatter'); 24 | $errorMessages = array($title, $message); 25 | $formattedBlock = $formatter->formatBlock($errorMessages, $style, true); 26 | $this->line($formattedBlock); 27 | } 28 | 29 | protected function sectionMessage($title, $message) 30 | { 31 | $formatter = $this->getHelperSet()->get('formatter'); 32 | $formattedLine = $formatter->formatSection( 33 | $title, 34 | $message 35 | ); 36 | $this->line($formattedLine); 37 | } 38 | } -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/Commands/MigrationsGeneratorCommand.php: -------------------------------------------------------------------------------- 1 | handler = $handler; 24 | } 25 | 26 | public function fire() 27 | { 28 | $database = $this->argument('database'); 29 | 30 | // Display some helpfull info 31 | if (empty($database)) { 32 | $this->comment("Preparing the migrations for database: {$this->getDatabaseName()}"); 33 | } else { 34 | $this->comment("Preparing the migrations for database {$database}"); 35 | } 36 | 37 | // Grab the options 38 | $ignore = $this->option('ignore'); 39 | 40 | if (empty($ignore)) { 41 | $this->handler->migrate($database); 42 | } else { 43 | $tables = explode(',', str_replace(' ', '', $ignore)); 44 | 45 | $this->handler->ignore($tables)->migrate($this->argument('database')); 46 | foreach (DbExporter::$ignore as $table) { 47 | $this->comment("Ignoring the {$table} table"); 48 | } 49 | } 50 | 51 | // Symfony style block messages 52 | $this->blockMessage('Success!', 'Database migrations generated in: ' . $this->handler->getMigrationsFilePath()); 53 | } 54 | 55 | protected function getArguments() 56 | { 57 | return array( 58 | array('database', InputArgument::OPTIONAL, 'Override the application database') 59 | ); 60 | } 61 | 62 | protected function getOptions() 63 | { 64 | return array( 65 | array('ignore', 'ign', InputOption::VALUE_REQUIRED, 'Ignore tables to export, seperated by a comma', null) 66 | ); 67 | } 68 | } -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/Commands/SeedGeneratorCommand.php: -------------------------------------------------------------------------------- 1 | handler = $handler; 25 | } 26 | 27 | public function fire() 28 | { 29 | $this->comment("Preparing the seeder class for database {$this->getDatabaseName()}"); 30 | 31 | // Grab the options 32 | $ignore = $this->option('ignore'); 33 | 34 | if (empty($ignore)) { 35 | $this->handler->seed(); 36 | } else { 37 | $tables = explode(',', str_replace(' ', '', $ignore)); 38 | $this->handler->ignore($tables)->seed(); 39 | foreach (DbExporter::$ignore as $table) { 40 | $this->comment("Ignoring the {$table} table"); 41 | } 42 | } 43 | 44 | // Symfony style block messages 45 | $formatter = $this->getHelperSet()->get('formatter'); 46 | $filename = $this->getFilename(); 47 | 48 | $errorMessages = array('Success!', "Database seed class generated in: {$filename}"); 49 | 50 | $formattedBlock = $formatter->formatBlock($errorMessages, 'info', true); 51 | $this->line($formattedBlock); 52 | } 53 | 54 | private function getFilename() 55 | { 56 | $filename = Str::camel($this->getDatabaseName()) . "TableSeeder"; 57 | return config('db-exporter.export_path.seeds')."{$filename}.php"; 58 | } 59 | 60 | protected function getOptions() 61 | { 62 | return array( 63 | array('ignore', 'ign', InputOption::VALUE_REQUIRED, 'Ignore tables to export, separated by a comma', null) 64 | ); 65 | } 66 | } -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/DbExportHandler.php: -------------------------------------------------------------------------------- 1 | migrator = $DbMigrations; 23 | $this->seeder = $DbSeeding; 24 | } 25 | 26 | /** 27 | * Create migrations from the given DB 28 | * @param String null $database 29 | * @return $this 30 | */ 31 | public function migrate($database = null) 32 | { 33 | $this->migrator->convert($database)->write(); 34 | 35 | return $this; 36 | } 37 | 38 | /** 39 | * @param null $database 40 | * @return $this 41 | */ 42 | public function seed($database = null) 43 | { 44 | $this->seeder->convert($database)->write(); 45 | 46 | return $this; 47 | } 48 | 49 | /** 50 | * Helper function to generate the migration and the seed in one command 51 | * @param null $database 52 | * @return $this 53 | */ 54 | public function migrateAndSeed($database = null) 55 | { 56 | // Run the migrator generator 57 | $this->migrator->convert($database)->write(); 58 | 59 | // Run the seeder generator 60 | $this->seeder->convert($database)->write(); 61 | 62 | return $this; 63 | } 64 | 65 | /** 66 | * Add tables to the ignore array 67 | * @param $tables 68 | * @return $this 69 | */ 70 | public function ignore($tables) 71 | { 72 | DbExporter::$ignore = array_merge(DbExporter::$ignore, (array)$tables); 73 | 74 | return $this; 75 | } 76 | 77 | /** 78 | * @return mixed 79 | */ 80 | public function getMigrationsFilePath() 81 | { 82 | return DbMigrations::$filePath; 83 | } 84 | 85 | public function uploadTo($remote) 86 | { 87 | DbExporter::$remote = $remote; 88 | 89 | return $this; 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/DbExportHandlerServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([__DIR__.'/../../config/config.php' => config_path('db-exporter.php')], 'config'); 28 | } 29 | 30 | public function register() 31 | { 32 | // Load the classes 33 | $this->loadClasses(); 34 | 35 | // Register the base export handler class 36 | $this->registerDbExportHandler(); 37 | 38 | // Handle the artisan commands 39 | $this->registerCommands(); 40 | 41 | // Load the alias 42 | $this->loadAlias(); 43 | 44 | // Default config 45 | $this->mergeConfigFrom( 46 | __DIR__.'/../../config/config.php', 'db-exporter' 47 | ); 48 | } 49 | 50 | /** 51 | * Load to classes 52 | */ 53 | protected function loadClasses() 54 | { 55 | // Instatiate a new DbMigrations class to send to the handler 56 | $this->migrator = new DbMigrations($this->getDatabaseName()); 57 | 58 | // Instatiate a new DbSeeding class to send to the handler 59 | $this->seeder = new DbSeeding($this->getDatabaseName()); 60 | 61 | // Instantiate the handler 62 | $this->handler = new DbExportHandler($this->migrator, $this->seeder); 63 | } 64 | 65 | /** 66 | * Get the database name from the app/config/database.php file 67 | * @return String 68 | */ 69 | private function getDatabaseName() 70 | { 71 | $connType = config('database.default'); 72 | $database = config('database.connections.' .$connType ); 73 | 74 | return $database['database']; 75 | } 76 | 77 | public function provides() 78 | { 79 | return array('DbExportHandler'); 80 | } 81 | 82 | /** 83 | * Register the needed commands 84 | */ 85 | public function registerCommands() 86 | { 87 | $this->registerMigrationsCommand(); 88 | $this->registerSeedsCommand(); 89 | $this->registerRemoteCommand(); 90 | $this->commands( 91 | 'dbe::migrations', 92 | 'dbe::seeds', 93 | 'dbe::remote' 94 | ); 95 | } 96 | 97 | /** 98 | * Register the migrations command 99 | */ 100 | protected function registerMigrationsCommand() 101 | { 102 | $this->app['dbe::migrations'] = $this->app->share(function() 103 | { 104 | return new Commands\MigrationsGeneratorCommand($this->handler); 105 | }); 106 | } 107 | 108 | /** 109 | * Register the seeds command 110 | */ 111 | protected function registerSeedsCommand() 112 | { 113 | $this->app['dbe::seeds'] = $this->app->share(function() 114 | { 115 | return new Commands\SeedGeneratorCommand($this->handler); 116 | }); 117 | } 118 | 119 | protected function registerRemoteCommand() 120 | { 121 | $this->app['dbe::remote'] = $this->app->share(function() 122 | { 123 | return new Commands\CopyToRemoteCommand(new Server); 124 | }); 125 | } 126 | 127 | /** 128 | * Register the Export handler class 129 | */ 130 | protected function registerDbExportHandler() 131 | { 132 | $this->app['DbExportHandler'] = $this->app->share(function() 133 | { 134 | return $this->handler; 135 | }); 136 | } 137 | 138 | /** 139 | * Load the alias = One less install step for the user 140 | */ 141 | protected function loadAlias() 142 | { 143 | $this->app->booting(function() 144 | { 145 | $loader = \Illuminate\Foundation\AliasLoader::getInstance(); 146 | $loader->alias('DbExportHandler', 'Nwidart\DbExporter\Facades\DbExportHandler'); 147 | 148 | // some users migrating from 5.0 don't have Str alias registered 149 | if (! class_exists('\Str')) { 150 | $loader->alias('Str',\Illuminate\Support\Str::class); 151 | } 152 | }); 153 | } 154 | 155 | } -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/DbExporter.php: -------------------------------------------------------------------------------- 1 | getPdo(); 21 | return $pdo->query('SELECT table_name FROM information_schema.tables WHERE table_schema="' . $this->database . '"'); 22 | } 23 | 24 | public function getTableIndexes($table) 25 | { 26 | $pdo = DB::connection()->getPdo(); 27 | return $pdo->query('SHOW INDEX FROM ' . $table . ' WHERE Key_name != "PRIMARY"'); 28 | } 29 | 30 | /** 31 | * Get all the columns for a given table 32 | * @param $table 33 | * @return mixed 34 | */ 35 | protected function getTableDescribes($table) 36 | { 37 | return DB::table('information_schema.columns') 38 | ->where('table_schema', '=', $this->database) 39 | ->where('table_name', '=', $table) 40 | ->get($this->selects); 41 | } 42 | 43 | /** 44 | * Grab all the table data 45 | * @param $table 46 | * @return mixed 47 | */ 48 | protected function getTableData($table) 49 | { 50 | return DB::table($table)->get(); 51 | } 52 | 53 | /** 54 | * Write the file 55 | * @return mixed 56 | */ 57 | abstract public function write(); 58 | 59 | /** 60 | * Convert the database to a usefull format 61 | * @param null $database 62 | * @return mixed 63 | */ 64 | abstract public function convert($database = null); 65 | 66 | /** 67 | * Put the converted stub into a template 68 | * @return mixed 69 | */ 70 | abstract protected function compile(); 71 | } -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/DbMigrations.php: -------------------------------------------------------------------------------- 1 | database = $database; 40 | } 41 | 42 | /** 43 | * Write the prepared migration to a file 44 | */ 45 | public function write() 46 | { 47 | // Check if convert method was called before 48 | // If not, call it on default DB 49 | if (!$this->customDb) { 50 | $this->convert(); 51 | } 52 | 53 | $schema = $this->compile(); 54 | $filename = date('Y_m_d_His') . "_create_" . $this->database . "_database.php"; 55 | self::$filePath = config('db-exporter.export_path.migrations')."{$filename}"; 56 | 57 | file_put_contents(self::$filePath, $schema); 58 | 59 | return self::$filePath; 60 | } 61 | 62 | /** 63 | * Convert the database to migrations 64 | * If none is given, use de DB from condig/database.php 65 | * @param null $database 66 | * @return $this 67 | */ 68 | public function convert($database = null) 69 | { 70 | if (!is_null($database)) { 71 | $this->database = $database; 72 | $this->customDb = true; 73 | } 74 | 75 | $tables = $this->getTables(); 76 | 77 | // Loop over the tables 78 | foreach ($tables as $key => $value) { 79 | // Do not export the ignored tables 80 | if (in_array($value['table_name'], self::$ignore)) { 81 | continue; 82 | } 83 | 84 | $down = "Schema::drop('{$value['table_name']}');"; 85 | $up = "Schema::create('{$value['table_name']}', function(Blueprint $" . "table) {\n"; 86 | 87 | $tableDescribes = $this->getTableDescribes($value['table_name']); 88 | // Loop over the tables fields 89 | foreach ($tableDescribes as $values) { 90 | $method = ""; 91 | $para = strpos($values->Type, '('); 92 | $type = $para > -1 ? substr($values->Type, 0, $para) : $values->Type; 93 | $numbers = ""; 94 | $nullable = $values->Null == "NO" ? "" : "->nullable()"; 95 | $default = empty($values->Default) ? "" : "->default('".$values->Default."')"; 96 | $unsigned = strpos($values->Type, "unsigned") === false ? '' : '->unsigned()'; 97 | 98 | switch ($type) { 99 | case 'int' : 100 | $method = 'integer'; 101 | break; 102 | case 'smallint' : 103 | $method = 'smallInteger'; 104 | break; 105 | case 'bigint' : 106 | $method = 'bigInteger'; 107 | break; 108 | case 'char' : 109 | case 'varchar' : 110 | $para = strpos($values->Type, '('); 111 | $numbers = ", " . substr($values->Type, $para + 1, -1); 112 | $method = 'string'; 113 | break; 114 | case 'float' : 115 | $method = 'float'; 116 | break; 117 | case 'double' : 118 | $para = strpos($values->Type, '('); # 6 119 | $numbers = ", " . substr($values->Type, $para + 1, -1); 120 | $method = 'double'; 121 | break; 122 | case 'decimal' : 123 | $para = strpos($values->Type, '('); 124 | $numbers = ", " . substr($values->Type, $para + 1, -1); 125 | $method = 'decimal'; 126 | break; 127 | case 'tinyint' : 128 | $method = 'boolean'; 129 | break; 130 | case 'date' : 131 | $method = 'date'; 132 | break; 133 | case 'timestamp' : 134 | $method = 'timestamp'; 135 | break; 136 | case 'datetime' : 137 | $method = 'dateTime'; 138 | break; 139 | case 'time' : 140 | $method = 'time'; 141 | break; 142 | case 'longtext' : 143 | $method = 'longText'; 144 | break; 145 | case 'mediumtext' : 146 | $method = 'mediumText'; 147 | break; 148 | case 'text' : 149 | $method = 'text'; 150 | break; 151 | case 'longblob': 152 | case 'blob' : 153 | $method = 'binary'; 154 | break; 155 | case 'enum' : 156 | $method = 'enum'; 157 | $para = strpos($values->Type, '('); # 4 158 | $options = substr($values->Type, $para + 1, -1); 159 | $numbers = ', array(' . $options . ')'; 160 | break; 161 | } 162 | 163 | if ($values->Key == 'PRI') { 164 | $method = 'increments'; 165 | } 166 | 167 | $up .= " $" . "table->{$method}('{$values->Field}'{$numbers}){$nullable}{$default}{$unsigned};\n"; 168 | } 169 | 170 | $tableIndexes = $this->getTableIndexes($value['table_name']); 171 | if (!is_null($tableIndexes) && count($tableIndexes)){ 172 | foreach ($tableIndexes as $index) { 173 | $up .= ' $' . "table->index('" . $index['Key_name'] . "');\n"; 174 | } 175 | } 176 | 177 | $up .= " });\n\n"; 178 | 179 | $this->schema[$value['table_name']] = array( 180 | 'up' => $up, 181 | 'down' => $down 182 | ); 183 | } 184 | 185 | return $this; 186 | } 187 | 188 | /** 189 | * Compile the migration into the base migration file 190 | * TODO use a template with seacrh&replace 191 | * @return string 192 | */ 193 | protected function compile() 194 | { 195 | $upSchema = ""; 196 | $downSchema = ""; 197 | 198 | // prevent of failure when no table 199 | if (!is_null($this->schema) && count($this->schema)) { 200 | foreach ($this->schema as $name => $values) { 201 | // check again for ignored tables 202 | if (in_array($name, self::$ignore)) { 203 | continue; 204 | } 205 | $upSchema .= " 206 | /** 207 | * Table: {$name} 208 | */ 209 | {$values['up']}"; 210 | 211 | $downSchema .= " 212 | {$values['down']}"; 213 | } 214 | } 215 | 216 | // Grab the template 217 | $template = File::get(__DIR__ . '/templates/migration.txt'); 218 | 219 | // Replace the classname 220 | $template = str_replace('{{name}}', "Create" . Str::title($this->database) . "Database", $template); 221 | 222 | // Replace the up and down values 223 | $template = str_replace('{{up}}', $upSchema, $template); 224 | $template = str_replace('{{down}}', $downSchema, $template); 225 | 226 | return $template; 227 | } 228 | 229 | } 230 | -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/DbMigrationsServiceProvider.php: -------------------------------------------------------------------------------- 1 | app['DbMigrations'] = $this->app->share(function() 34 | { 35 | $connType = config('database.default'); 36 | $database = config('database.connections.' .$connType ); 37 | return new DbMigrations($database); 38 | }); 39 | 40 | $this->app->booting(function() 41 | { 42 | $loader = \Illuminate\Foundation\AliasLoader::getInstance(); 43 | $loader->alias('DbMigrations', 'Nwidart\DbExporter\Facades\DbMigrations'); 44 | }); 45 | } 46 | 47 | /** 48 | * Get the services provided by the provider. 49 | * 50 | * @return array 51 | */ 52 | public function provides() 53 | { 54 | return array('DbMigrations'); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/DbSeeding.php: -------------------------------------------------------------------------------- 1 | database = $database; 29 | } 30 | 31 | /** 32 | * Write the seed file 33 | */ 34 | public function write() 35 | { 36 | // Check if convert method was called before 37 | // If not, call it on default DB 38 | if (!$this->customDb) { 39 | $this->convert(); 40 | } 41 | 42 | $seed = $this->compile(); 43 | 44 | $filename = Str::camel($this->database) . "TableSeeder"; 45 | 46 | file_put_contents(config('db-exporter.export_path.seeds')."{$filename}.php", $seed); 47 | } 48 | 49 | /** 50 | * Convert the database tables to something usefull 51 | * @param null $database 52 | * @return $this 53 | */ 54 | public function convert($database = null) 55 | { 56 | if (!is_null($database)) { 57 | $this->database = $database; 58 | $this->customDb = true; 59 | } 60 | 61 | // Get the tables for the database 62 | $tables = $this->getTables(); 63 | 64 | $stub = ""; 65 | // Loop over the tables 66 | foreach ($tables as $key => $value) { 67 | // Do not export the ignored tables 68 | if (in_array($value['table_name'], self::$ignore)) { 69 | continue; 70 | } 71 | $tableName = $value['table_name']; 72 | $tableData = $this->getTableData($value['table_name']); 73 | $insertStub = ""; 74 | 75 | foreach ($tableData as $obj) { 76 | $insertStub .= " 77 | array(\n"; 78 | foreach ($obj as $prop => $value) { 79 | $insertStub .= $this->insertPropertyAndValue($prop, $value); 80 | } 81 | 82 | if (count($tableData) > 1) { 83 | $insertStub .= " ),\n"; 84 | } else { 85 | $insertStub .= " )\n"; 86 | } 87 | } 88 | 89 | if ($this->hasTableData($tableData)) { 90 | $stub .= " 91 | DB::table('" . $tableName . "')->insert(array( 92 | {$insertStub} 93 | ));"; 94 | } 95 | } 96 | 97 | $this->seedingStub = $stub; 98 | 99 | return $this; 100 | } 101 | 102 | /** 103 | * Compile the current seedingStub with the seed template 104 | * @return mixed 105 | */ 106 | protected function compile() 107 | { 108 | // Grab the template 109 | $template = File::get(__DIR__ . '/templates/seed.txt'); 110 | 111 | // Replace the classname 112 | $template = str_replace('{{className}}', \Str::camel($this->database) . "TableSeeder", $template); 113 | $template = str_replace('{{run}}', $this->seedingStub, $template); 114 | 115 | return $template; 116 | } 117 | 118 | private function insertPropertyAndValue($prop, $value) 119 | { 120 | $prop = addslashes($prop); 121 | $value = addslashes($value); 122 | if (is_numeric($value)) { 123 | return " '{$prop}' => {$value},\n"; 124 | } elseif($value == '') { 125 | return " '{$prop}' => NULL,\n"; 126 | } else { 127 | return " '{$prop}' => '{$value}',\n"; 128 | } 129 | } 130 | 131 | /** 132 | * @param $tableData 133 | * @return bool 134 | */ 135 | public function hasTableData($tableData) 136 | { 137 | return count($tableData) >= 1; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/Exceptions/InvalidDatabaseException.php: -------------------------------------------------------------------------------- 1 | ignoredFiles)) { 26 | continue; 27 | } 28 | 29 | // Capture the uploaded files for display later 30 | self::$uploadedFiles[$what][] = $remotePath . $file; 31 | 32 | // Copy the files 33 | SSH::into($this->getRemoteName())->put( 34 | $localPath .'/' . $file, 35 | $remotePath . $file 36 | ); 37 | } 38 | 39 | return true; 40 | } 41 | 42 | private function getRemoteName() 43 | { 44 | // For now static from he config file. 45 | return config('db-exporter.remote.name'); 46 | } 47 | } -------------------------------------------------------------------------------- /src/Nwidart/DbExporter/facades/DbExportHandler.php: -------------------------------------------------------------------------------- 1 | array( 7 | 'name' => 'production', 8 | 'migrations' => '/home/htdocs/testing/migrations/', 9 | 'seeds' => '/home/htdocs/testing/seeds/' 10 | ), 11 | 'export_path' => array( 12 | 'migrations' => database_path('migrations').'/', 13 | 'seeds' => database_path('seeds').'/' 14 | ) 15 | ); 16 | -------------------------------------------------------------------------------- /tests/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nWidart/DbExporter/91330e5b89c8054320eaa475af50fc1d0fbf405b/tests/.gitkeep --------------------------------------------------------------------------------