├── .env-sample ├── LICENSE ├── README.md ├── composer.json ├── database-export.sh ├── database-import.sh ├── database-prepare.sh └── database-update.sh /.env-sample: -------------------------------------------------------------------------------- 1 | DOMAIN_REMOTE=www.example.com 2 | DOMAIN_LOCAL=www.example.local 3 | 4 | DB_HOST=localhost 5 | DB_DATABASE=example 6 | DB_USERNAME=root 7 | DB_PASSWORD=password 8 | 9 | REMOTE_DB_HOST=123.123.123.123 10 | REMOTE_DB_DATABASE=example 11 | REMOTE_DB_USERNAME=root 12 | REMOTE_DB_PASSWORD=password -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Scott Salisbury 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Database Sync 2 | 3 | When working on an active project, your local database may become too out of date from the database in staging or production and make local development difficult or unpredictable. 4 | 5 | DB Sync provides scripts to quickly update a local MySQL development database with a remote staging or production database, as well as the ability to run safe search/replace on your local database in preparation for deploying to a remote server. It assumes that your remote database is externally accessable via an IP whitelist or similar. 6 | 7 | *Disclaimer: These scripts and commands were originally created for use internally within our development team to speed up common, repetitive tasks. However, they may be of some use to others. Feel free to use in your own projects, your mileage may vary.* 8 | 9 | ## Requirements 10 | 11 | * Composer 12 | * PHP >= 5.3.0 13 | * A local development environment, such as Vagrant. 14 | 15 | ## Notes 16 | 17 | * These scripts require a .env config file in the project root . however it should work with other projects, such as Laravel 5. 18 | 19 | ## Installation 20 | 21 | Run `composer require "waelwalid/laravel-database-sync:1.*" --dev` from the root of your project. 22 | 23 | Alternatively, you can manually add `"waelwalid/laravel-database-sync": "1.*"` to your `composer.json` file: 24 | 25 | ``` 26 | "require-dev": { 27 | "waelwalid/laravel-database-sync": "1.*" 28 | } 29 | ``` 30 | 31 | Then add the following scripts to your `composer.json` file: 32 | 33 | ``` 34 | "scripts": { 35 | "database-update" : [ 36 | "vendor/waelwalid/laravel-database-sync/database-update.sh" 37 | ], 38 | "database-prepare" : [ 39 | "vendor/waelwalid/laravel-database-sync/database-prepare.sh" 40 | ], 41 | "database-import" : [ 42 | "vendor/waelwalid/laravel-database-sync/database-import.sh" 43 | ], 44 | "database-export" : [ 45 | "vendor/waelwalid/laravel-database-sync/database-export.sh" 46 | ] 47 | } 48 | ``` 49 | 50 | Run the `composer update` command from the root of your project. 51 | 52 | Create a `.env` file in the root of your project and add/update the following configuration options: 53 | 54 | ``` 55 | DOMAIN_REMOTE=www.example.com 56 | DOMAIN_LOCAL=www.example.local 57 | 58 | DB_HOST=localhost 59 | DB_DATABASE=example 60 | DB_USERNAME=root 61 | DB_PASSWORD=password 62 | 63 | REMOTE_DB_HOST=123.123.123.123 64 | REMOTE_DB_DATABASE=example 65 | REMOTE_DB_USERNAME=root 66 | REMOTE_DB_PASSWORD=password 67 | ``` 68 | 69 | ## Usage 70 | 71 | From the root of your project, you will be able to run the following composer commands: 72 | 73 | * ***composer database-update*** - When working on an active project, your local database might become too out of date from the database in staging or production. This command will backup and empty your locally configured database and update it with a copy of your remote or production database. This requires all `DB_*` and `REMOTE_DB_*` options to be set in the .env file and also assumes your remote database is accessible externally. 74 | 75 | * ***composer database-prepare*** - When developing locally, links to images and assets created within a CMS might be referencing your local development web address and won't work in staging or production. This command will run a safe search/replace script on your locally configured database, replacing all instances of `DOMAIN_LOCAL` with `DOMAIN_REMOTE` configured in the .env file. The database will then be exported to `dumps/prepared-database-YYYY.MM.DD-HH.MM.SS.sql` ready for deployment. 76 | 77 | * ***composer database-import*** - If the file `setup/database.sql` exists in the project root, this command will import the file into your local database configured in the .env file. This is useful if you're working on a project and want another member of the team to get quickly set up with working copy of the database. 78 | 79 | * ***composer database-export*** - This command will export a copy of your local database configured in the .env file and save it to `setup/database.sql`. If this file exists it will be overwritten. This is useful to quickly take a snapshot of your current development database to be shared with others. 80 | 81 | ## Config 82 | 83 | See below for an explanation of each configuration option used within the .env file. 84 | 85 | * ***DOMAIN_REMOTE*** - It should point to your remote or production environment (if available) and not include http:// or trailing slashes. Example: `www.example.com` or `subdomain.example.com`. 86 | 87 | * ***DOMAIN_LOCAL*** - It should not include http:// or trailing slashes. Example: `www.example.local` or `subdomain.example.local`. 88 | 89 | * ***DB_**** - Provides options to set the local database connection details. 90 | 91 | * ***REMOTE\_DB_**** - Provides options to set the remote staging or production database connection details. 92 | 93 | 94 | ## Donate 95 | If you like this package, don't hesitate to give it a [Start](https://github.com/waelwalid/laravel-database-sync) or donate via [Paypal](https://paypal.me/WaelWalid) . -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "waelwalid/laravel-database-sync", 3 | "description": "Helper scripts to quickly synchronise a local MySQL database with a remote database, as well as prepare a local database for deployment to a remote server.", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Wael Walid", 8 | "email": "wael.walid91@gmail.com" 9 | } 10 | ], 11 | "require": { 12 | "interconnectit/search-replace-db": "^3.1" 13 | }, 14 | "scripts": { 15 | "database-update" : [ 16 | "vendor/waelwalid/laravel-database-sync/database-update.sh" 17 | ], 18 | "database-prepare" : [ 19 | "vendor/waelwalid/laravel-database-sync/database-prepare.sh" 20 | ], 21 | "database-import" : [ 22 | "vendor/waelwalid/laravel-database-sync/database-import.sh" 23 | ], 24 | "database-export" : [ 25 | "vendor/waelwalid/laravel-database-sync/database-export.sh" 26 | ] 27 | }, 28 | "minimum-stability": "dev" 29 | } 30 | -------------------------------------------------------------------------------- /database-export.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Config file 4 | SOURCE="${BASH_SOURCE[0]}" 5 | while [ -h "$SOURCE" ]; do 6 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 7 | SOURCE="$( readlink "$SOURCE" )" 8 | [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" 9 | done 10 | 11 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 12 | 13 | CONFIG=${DIR%/*/*/*} 14 | 15 | # Import config settings 16 | source "$CONFIG/.env" 17 | 18 | # Local config 19 | LOCAL_DATABASE_HOST=$DB_HOST 20 | LOCAL_DATABASE_NAME=$DB_DATABASE 21 | LOCAL_DATABASE_USER=$DB_USERNAME 22 | LOCAL_DATABASE_PASS=$DB_PASSWORD 23 | 24 | # Create directory to store dumps 25 | mkdir -p $CONFIG/setup 26 | 27 | # Check for database connections 28 | if mysql -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS -e 'use '"$LOCAL_DATABASE_NAME"; then 29 | 30 | # Download database dump 31 | echo Exporting database \'$LOCAL_DATABASE_NAME\' from local server: $LOCAL_DATABASE_HOST 32 | mysqldump -v -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS $LOCAL_DATABASE_NAME > $CONFIG/setup/database.sql 33 | 34 | echo COMPLETE: Local database \'$LOCAL_DATABASE_NAME\' exported: setup/database.sql 35 | 36 | else 37 | echo ERROR: Could not connect to local database: $LOCAL_DATABASE_NAME 38 | fi 39 | -------------------------------------------------------------------------------- /database-import.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Config file 4 | SOURCE="${BASH_SOURCE[0]}" 5 | while [ -h "$SOURCE" ]; do 6 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 7 | SOURCE="$( readlink "$SOURCE" )" 8 | [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" 9 | done 10 | 11 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 12 | 13 | CONFIG=${DIR%/*/*/*} 14 | 15 | # Import config settings 16 | source "$CONFIG/.env" 17 | 18 | # Local config 19 | LOCAL_DATABASE_HOST=$DB_HOST 20 | LOCAL_DATABASE_NAME=$DB_DATABASE 21 | LOCAL_DATABASE_USER=$DB_USERNAME 22 | LOCAL_DATABASE_PASS=$DB_PASSWORD 23 | 24 | # Create directory to store dumps 25 | mkdir -p $CONFIG/setup 26 | 27 | # # Check for database connections 28 | # if ! mysql -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS -e 'use '"$LOCAL_DATABASE_NAME" &> /dev/null; then 29 | 30 | # if [ -f $CONFIG/setup/database.sql ]; then 31 | 32 | # # Create local database 33 | # echo Creating local database: $LOCAL_DATABASE_NAME 34 | # mysqladmin -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS create $LOCAL_DATABASE_NAME 35 | 36 | # echo Database created: $LOCAL_DATABASE_NAME 37 | 38 | # # Upload dump to local database 39 | # echo Importing database \'setup/database.sql\' to local server: $LOCAL_DATABASE_HOST 40 | # mysql -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS $LOCAL_DATABASE_NAME < $CONFIG/setup/database.sql 41 | 42 | # echo COMPLETE: Database \'setup/database.sql\' imported: $LOCAL_DATABASE_NAME 43 | 44 | # else 45 | # echo ERROR: Database file not found: setup/database.sql 46 | # fi 47 | 48 | # else 49 | # echo ERROR: Database \'$LOCAL_DATABASE_NAME\' already exists 50 | # fi 51 | 52 | 53 | # Check for database connections 54 | if ! mysql -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS -e 'use '"$LOCAL_DATABASE_NAME" &> /dev/null; then 55 | 56 | if [ -f $CONFIG/setup/database.sql ]; then 57 | 58 | # Create local database 59 | echo Creating local database: $LOCAL_DATABASE_NAME 60 | mysqladmin -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS create $LOCAL_DATABASE_NAME 61 | 62 | echo Database created: $LOCAL_DATABASE_NAME 63 | 64 | # Upload dump to local database 65 | echo Importing database \'setup/database.sql\' to local server: $LOCAL_DATABASE_HOST 66 | mysql -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS $LOCAL_DATABASE_NAME < $CONFIG/setup/database.sql 67 | 68 | echo COMPLETE: Database \'setup/database.sql\' imported: $LOCAL_DATABASE_NAME 69 | 70 | else 71 | echo ERROR: Database file not found: setup/database.sql 72 | fi 73 | 74 | else 75 | # Upload dump to local database 76 | echo Importing database \'setup/database.sql\' to local server: $LOCAL_DATABASE_HOST 77 | mysql -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS $LOCAL_DATABASE_NAME < $CONFIG/setup/database.sql 78 | 79 | echo COMPLETE: Database \'setup/database.sql\' imported: $LOCAL_DATABASE_NAME 80 | fi -------------------------------------------------------------------------------- /database-prepare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Config file 4 | SOURCE="${BASH_SOURCE[0]}" 5 | while [ -h "$SOURCE" ]; do 6 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 7 | SOURCE="$( readlink "$SOURCE" )" 8 | [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" 9 | done 10 | 11 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 12 | 13 | CONFIG=${DIR%/*/*/*} 14 | 15 | # Import config settings 16 | source "$CONFIG/.env" 17 | 18 | # Local config 19 | LOCAL_DATABASE_HOST=$DB_HOST 20 | LOCAL_DATABASE_NAME=$DB_DATABASE 21 | LOCAL_DATABASE_USER=$DB_USERNAME 22 | LOCAL_DATABASE_PASS=$DB_PASSWORD 23 | 24 | # Current timestamp 25 | CURRENT_TIME=$(date "+%Y.%m.%d-%H.%M.%S") 26 | 27 | # Create directory to store dumps 28 | mkdir -p $CONFIG/dumps 29 | 30 | # Check for database connections 31 | if mysql -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS -e 'use '"$LOCAL_DATABASE_NAME"; then 32 | 33 | echo Backing up local database \'$LOCAL_DATABASE_NAME\': $LOCAL_DATABASE_HOST 34 | mysqldump -v -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS $LOCAL_DATABASE_NAME > $CONFIG/dumps/local-database-$CURRENT_TIME.sql 35 | 36 | if [ -f vendor/interconnectit/search-replace-db/srdb.cli.php ]; then 37 | 38 | echo Running search and replace: $LOCAL_DATABASE_NAME 39 | 40 | # Run find/replace script 41 | php vendor/interconnectit/search-replace-db/srdb.cli.php -h $LOCAL_DATABASE_HOST -n $LOCAL_DATABASE_NAME -u $LOCAL_DATABASE_USER -p $LOCAL_DATABASE_PASS -s "$DOMAIN_LOCAL" -r "$DOMAIN_REMOTE" 42 | echo Search and replace complete: $LOCAL_DATABASE_NAME 43 | 44 | echo Exporting prepared database: $LOCAL_DATABASE_NAME 45 | 46 | mysqldump -v -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS $LOCAL_DATABASE_NAME > $CONFIG/dumps/prepared-database-$CURRENT_TIME.sql 47 | echo COMPLETE: Database exported and replaced \'$DOMAIN_LOCAL\' with \'$DOMAIN_REMOTE\': prepared-database-$CURRENT_TIME.sql 48 | else 49 | echo ERROR: Script not found: vendor/interconnectit/search-replace-db/srdb.cli.php 50 | fi 51 | 52 | else 53 | echo ERROR: Could not connect to the database: $LOCAL_DATABASE_NAME 54 | fi 55 | -------------------------------------------------------------------------------- /database-update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Config file 4 | SOURCE="${BASH_SOURCE[0]}" 5 | while [ -h "$SOURCE" ]; do 6 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 7 | SOURCE="$( readlink "$SOURCE" )" 8 | [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" 9 | done 10 | 11 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 12 | 13 | CONFIG=${DIR%/*/*/*} 14 | 15 | # Import config settings 16 | source "$CONFIG/.env" 17 | 18 | # Local config 19 | LOCAL_DATABASE_HOST=$DB_HOST 20 | LOCAL_DATABASE_NAME=$DB_DATABASE 21 | LOCAL_DATABASE_USER=$DB_USERNAME 22 | LOCAL_DATABASE_PASS=$DB_PASSWORD 23 | 24 | # Remote config 25 | REMOTE_DATABASE_HOST=$REMOTE_DB_HOST 26 | REMOTE_DATABASE_NAME=$REMOTE_DB_DATABASE 27 | REMOTE_DATABASE_USER=$REMOTE_DB_USERNAME 28 | REMOTE_DATABASE_PASS=$REMOTE_DB_PASSWORD 29 | 30 | # Current timestamp 31 | CURRENT_TIME=$(date "+%Y.%m.%d-%H.%M.%S") 32 | 33 | # Create directory to store dumps 34 | mkdir -p $CONFIG/dumps 35 | 36 | echo Backing up local database: $LOCAL_DATABASE_NAME 37 | mysqldump -v -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS $LOCAL_DATABASE_NAME > $CONFIG/dumps/local-database-$CURRENT_TIME.sql 38 | 39 | # Delete local database 40 | echo Dropping local database: $LOCAL_DATABASE_NAME 41 | mysqladmin -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS drop $LOCAL_DATABASE_NAME -f 42 | 43 | # Create local database 44 | echo Creating local database: $LOCAL_DATABASE_NAME 45 | mysqladmin -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS create $LOCAL_DATABASE_NAME 46 | 47 | # Check for database connections 48 | if mysql -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS -e 'use '"$LOCAL_DATABASE_NAME" && mysql -h $REMOTE_DATABASE_HOST -u $REMOTE_DATABASE_USER -p$REMOTE_DATABASE_PASS -e 'use '"$REMOTE_DATABASE_NAME"; then 49 | 50 | # Download database dump 51 | echo Exporting database \'$REMOTE_DATABASE_NAME\' from remote server: $REMOTE_DATABASE_HOST 52 | mysqldump -v -h $REMOTE_DATABASE_HOST -u $REMOTE_DATABASE_USER -p$REMOTE_DATABASE_PASS $REMOTE_DATABASE_NAME > $CONFIG/dumps/remote-database-$CURRENT_TIME.sql 53 | cp $CONFIG/dumps/remote-database-$CURRENT_TIME.sql $CONFIG/setup/ 54 | mv $CONFIG/setup/remote-database-$CURRENT_TIME.sql $CONFIG/setup/database.sql 55 | 56 | echo Remote database exported: remote-database-$CURRENT_TIME.sql 57 | 58 | echo Now We Importing The New Database 59 | composer database-import 60 | 61 | # Upload dump to local database 62 | # echo Importing database \'remote-database-$CURRENT_TIME.sql\' to local server: $LOCAL_DATABASE_HOST 63 | # mysql -h $LOCAL_DATABASE_HOST -u $LOCAL_DATABASE_USER -p$LOCAL_DATABASE_PASS $LOCAL_DATABASE_NAME < $CONFIG/dumps/remote-database-$CURRENT_TIME.sql 64 | 65 | echo COMPLETE: Database update complete: $LOCAL_DATABASE_NAME 66 | 67 | else 68 | echo ERROR: Could not connect to the local or remote database 69 | fi --------------------------------------------------------------------------------