8

I just installed Cartalyst's Sentry 2 in a Laravel 4 application but I found out that I have to run that package's migrations separately by specifying --package=cartalyst/sentry, which makes automatic deployment impossible.

Is there a way to run php artisan migrate and have it run Sentry's migrations as well?

borfast
  • 2,194
  • 1
  • 15
  • 34
  • 1
    The only way I can think of doing this is by customing your own artisan command to try and load as many migrations from packages as possible. L4 (as far as I am aware) doesn't support this otherwise, maybe due to security issues of people installing a package then having migrated migrations into from packages that could drop existing tables. – David May 29 '13 at 16:09
  • I'm not sure I follow but if you're concerned about package migrations that could drop existing tables, it won't make any difference if Laravel requires a '--package' argument to run them or if they can be run simply with `php artisan migrate`. Read the package migrations first, if you're concerned about it. What's at stake is the ease of use. I don't recall how Rails does it but Django allows you to run all the available migrations, both your own and from any installed packages. Having to manually run the migrations for each package doesn't make much sense and it's an annoying waste of time. – borfast Mar 15 '15 at 11:57
  • Also, the security implication could be mitigated if Laravel would implement something I suggested some time ago: "namespaces" for packages in the DB. Django creates every table with a prefix that is the name of the package the migration belongs to. This fixes not only the potential security problem of a third-party migration dropping one of your own tables, but also solves the problem of table name clashes if one package needs to create a table with the same name as another package. – borfast Mar 15 '15 at 11:59
  • If anyone is curious, here's my original suggestion for adding "namespaces" (prefixes) to DB tables: https://github.com/laravel/framework/issues/3265 – borfast Mar 15 '15 at 12:42
  • There is a difference for L4.x & L5.x Maybe this helps : https://stackoverflow.com/a/46714177/3256489 – 4givN Oct 12 '17 at 16:08

4 Answers4

5

After Laravel 5 there is a better way to solve this:

Create your migrations in package's /database/migrations folder . After that, in package's service provider create a boot method, referencing the migrations folder

public function boot()
{
    $this->loadMigrationsFrom(__DIR__ . 
    '/database/migrations');
}

Now, on the top level folder (the main app, which required this package), you can run the default migrate command ( php artisan migrate ) and it will automatically find the packages migrations througth the loadMigrationsFrom method

ANSWER COPIED FROM: http://voerro.com/en/tutorials/r/developing-and-distributing-laravel-5-packages/3

vimuth
  • 5,064
  • 33
  • 79
  • 116
Lucas Caponi
  • 51
  • 1
  • 3
  • Thanks for the improved answer. :) Why does it still require you to do extra work (the boot() function), though, instead of just detecting the migrations in the package and running them? – borfast Aug 28 '19 at 23:31
  • I really don't know why. Makes sense it becomes the default behavior someday. – Lucas Caponi Aug 29 '19 at 13:03
4

What I usually do in a scenario like this is publish the package migrations though the command:

php artisan migrate:publish vendor/package

This copies the migration files from any given package to your migrations folder.

  • 1
    It does, but that also means you need to do it every single time you update a package, just to make sure you're not missing any new migrations, which, again, makes automatic deployments harder than they need to be. – borfast Apr 28 '15 at 15:03
  • it should be `php artisan vendor:publish vendor/package` – Andrea Mauro Jul 09 '19 at 11:55
1

I created a composer script to replace php artisan migrate ...... The script runs my migrations and the vendor's migrations everything at once.

My composer scripts is

"scripts": {
    "migrate": [
        "php artisan migrate --env=$LARAVEL_ENV",
        "php artisan migrate --package=\"cartalyst/sentry\" --env=$LARAVEL_ENV",
        "php artisan migrate --package=\"mrjuliuss/syntara\" --env=$LARAVEL_ENV",
        "php artisan migrate --package=\"filmoteca/static-pages\" --env=$LARAVEL_ENV"
    ]
}

Then you can run the migration with LARAVEL_ENV=prod composer run-script migrate

To pass parameter to the script I use environment variables. In the previous example I set the environment variable LARAVEL_ENV to prod so the migration use the production database connection.

You can always create a alias in your local machine to short the command. For example alias migrate="LARAVEL_ENV=local composer run-script migrate"

I think this approach is good because when you are going to add a new package to your composer.json and this package has a migration you add the package and the package's migration in the same file. So, you do not forget add/remove the migration of a package.

This is a complete composer.json with the script

Victor Aguilar
  • 455
  • 4
  • 18
  • 1
    I think I did something similar but just like every other solution, it is unnecessary extra work. Thankfully I barely even remember this, as I have moved on to greener pastures (i.e. away from PHP). – borfast May 14 '16 at 13:22
1

The 3rd party package must declare a Service Provider, that declare migrations.

As you can see at https://github.com/laravel/passport/blob/9.x/src/PassportServiceProvider.php#L80:

protected function registerMigrations()
    {
        if (Passport::$runsMigrations && ! config('passport.client_uuids')) {
            return $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
        }
    }
Thomas Decaux
  • 21,738
  • 2
  • 113
  • 124