├── .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 | [](https://scrutinizer-ci.com/g/nWidart/DbExporter/)
2 | [](https://packagist.org/packages/nwidart/db-exporter) [](https://packagist.org/packages/nwidart/db-exporter) [](https://packagist.org/packages/nwidart/db-exporter) [](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 |
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
--------------------------------------------------------------------------------