Skip to content

Laravel utility to keep records synced between enviroments through source control

License

Notifications You must be signed in to change notification settings

nullthoughts/laravel-data-sync

Folders and files

NameName
Last commit message
Last commit date

Latest commit

8c6bcd0 · Dec 11, 2024
Dec 11, 2024
Dec 11, 2024
Dec 11, 2024
Dec 11, 2024
Dec 11, 2024
Dec 11, 2024
Dec 11, 2024
Oct 16, 2019
Oct 16, 2019
Oct 15, 2019
Dec 11, 2024
May 17, 2022
Dec 11, 2024
Dec 11, 2024
Sep 7, 2022
Dec 11, 2024
Dec 11, 2024

Repository files navigation

Total Downloads Latest Stable Version Travis CI Build Status: Master

Laravel Data Sync

Laravel utility to keep records synchronized between environments through source control

V3.1 branch Notes (Work in progress)

  • Adds support for Laravel 8+ models directory in config/data-sync.php:
'namespace' => '\\App\\Models\\',
  • Adds ability to export existing Models to data sync files:
php artisan data:export User --criteria=name --criteria=email --except=id

which generates

[
    {
        "_name": "Cameron Frye",
        "properties->title": "Best Friend",
        "phone_numbers->mobile": "555-555-5556",
        "_email": "noreply@buellerandco.com",
    }
]
  • Further work is required to support remote disks. For testing & development of new V3.1 features, use composer require nullthoughts/laravel-data-sync:v3.1.x-dev

Installation

You can install this package via composer:

composer require nullthoughts/laravel-data-sync

Or add this line in your composer.json, inside of the require section:

{
    "require": {
        "nullthoughts/laravel-data-sync": "^1.0",
    }
}

then run composer install

Usage

  • Run php artisan vendor:publish --provider="nullthoughts\LaravelDataSync\DataSyncBaseServiceProvider" --tag="data-sync-config" to publish config file. Specify directory for sync data files (default is a new sync directory in the project root)
  • Create a JSON file for each model, using the model name as the filename. Example: Product.json would update the Product model
  • Use nested arrays in place of hardcoded IDs for relationships
  • Run php artisan data:sync (or php artisan data:sync --model={model} with the model flag to specify a model)

Optional

If using Laravel Forge, you can have the data sync run automatically on deploy. Edit your deploy script in Site -> App to include:

if [ -f artisan ]
then
    php artisan migrate --force
    php artisan data:sync
fi

Notes

  • use studly case for model name relationships as JSON keys (example: 'option_group' => 'OptionGroup'). This is important for case sensitive file systems.
  • empty values are skipped
  • the criteria/attributes for updateOrCreate are identified with a leading underscore
  • nested values represent relationships and are returned using where($key, $value)->first()->id
  • order of import can be set in config/data-sync.php with an array:
return [
    'path' => base_path('sync'),
    'order' => [
        'Role',
        'Supervisor',
    ]
];

Examples

User.json:

[
    {
        "name": "Ferris Bueller",
        "properties->title": "Leisure Consultant",
        "phone_numbers->mobile": "555-555-5555",
        "phone_numbers->office": "",
        "_email": "ferris@buellerandco.com",
        "department": {
            "name": "Management",
            "location": {
                "name": "Chicago"
            }
        }
    }
]

translates to...

User::updateOrCreate([
    'email' => 'ferris@buellerandco.com',
],[
    'name' => 'Ferris Bueller',
    'properties->title' => 'Leisure Consultant',
    'phone_numbers->mobile' => '555-555-5555',
    'department_id' => Department::where('name', 'Management')
                        ->where('location_id', Location::where('name', 'Chicago')->first()->id)
                        ->first()
                        ->id,
]);

Role.json:

[
    {
        "_slug": "update-student-records"
    },
    {
        "_slug": "borrow-ferrari"
    },
    {
        "_slug": "destroy-ferrari"
    }
]

translates to...

    Role::updateOrCreate(['slug' => 'update-student-records']);

    Role::updateOrCreate(['slug' => 'borrow-ferrari']);

    Role::updateOrCreate(['slug' => 'destroy-ferrari']);

RoleUser.json (pivot table with model):

[
    {
        "_user": {
            "email": "ferris@buellerandco.com"
        },
        "_role": {
            "slug": "update-student-records"
        }
    },
    {
        "_user": {
            "email": "ferris@buellerandco.com"
        },
        "_role": {
            "slug": "borrow-ferrari"
        }
    },
    {
        "_user": {
            "email": "ferris@buellerandco.com"
        },
        "_role": {
            "slug": "destroy-ferrari"
        }
    }
]

translates to...

    RoleUser::updateOrCreate([
        'user_id' => User::where('email', 'ferris@buellerandco.com')->first()->id,
        'role_id' => Role::where('slug', 'update-student-records')->first()->id,
    ]);

    RoleUser::updateOrCreate([
        'user_id' => User::where('email', 'ferris@buellerandco.com')->first()->id,
        'role_id' => Role::where('slug', 'borrow-ferrari')->first()->id,
    ]);

    RoleUser::updateOrCreate([
        'user_id' => User::where('email', 'ferris@buellerandco.com')->first()->id,
        'role_id' => Role::where('slug', 'destroy-ferrari')->first()->id,
    ]);