11

so I have created my own blog package in a structure of Packages/Sitemanager/Blog I have a service provider that looks like the following:

namespace Sitemanager\Blog;

use Illuminate\Support\ServiceProvider as LaravelServiceProvider;

class BlogServiceProvider extends LaravelServiceProvider {

    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = false;

    /**
     * Bootstrap the application events.
     *
     * @return void
     */
    public function boot() {

        $this->handleConfigs();
        $this->handleMigrations();
        $this->handleViews();
        $this->handleRoutes();
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register() {

        // Bind any implementations.
        $this->app->make('Sitemanager\Blog\Controllers\BlogController');
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides() {

        return [];
    }

    private function handleConfigs() {

        $configPath = __DIR__ . '/config/blog.php';

        $this->publishes([$configPath => config_path('blog.php')]);

        $this->mergeConfigFrom($configPath, 'blog');
    }

    private function handleTranslations() {

        $this->loadTranslationsFrom(__DIR__.'/lang', 'blog');
    }

    private function handleViews() {

        $this->loadViewsFrom(__DIR__.'/views', 'blog');

        $this->publishes([__DIR__.'/views' => base_path('resources/views/vendor/blog')]);
    }

    private function handleMigrations() {

        $this->publishes([__DIR__ . '/migrations' => base_path('database/migrations')]);
    }

    private function handleRoutes() {

        include __DIR__.'/routes.php';
    }
}

Now, what i would like to do is run the migrations dynamically if they have never been run before or within an installation process i suppose. I've seen in older documentation you could so something like this:

Artisan::call('migrate', array('--path' => 'app/migrations'));

However, this is invalid in laravel 5, how can I approach this?

mdixon18
  • 1,199
  • 4
  • 14
  • 35

3 Answers3

32
Artisan::call('migrate', array('--path' => 'app/migrations'));

will work in Laravel 5, but you'll likely need to make a couple tweaks.

First, you need a use Artisan; line at the top of your file (where use Illuminate\Support\ServiceProvider... is), because of Laravel 5's namespacing. (You can alternatively do \Artisan::call - the \ is important).

You likely also need to do this:

Artisan::call('migrate', array('--path' => 'app/migrations', '--force' => true));

The --force is necessary because Laravel will, by default, prompt you for a yes/no in production, as it's a potentially destructive command. Without --force, your code will just sit there spinning its wheels (Laravel's waiting for a response from the CLI, but you're not in the CLI).

enter image description here

I'd encourage you to do this stuff somewhere other than the boot method of a service provider. These can be heavy calls (relying on both filesystem and database calls you don't want to make on every pageview). Consider an explicit installation console command or route instead.

ceejayoz
  • 176,543
  • 40
  • 303
  • 368
  • Using my boot command for now, I will probably look to have some kind of installation command that runs after being installed (not sure of best way to do this at the moment). Anyway doing \Artisan::call('migrate', array('--path' => 'packages/sitemanager/blog/migrations', '--force' => true)); worked for me, i could see the changes made to the database. How would you do the installation process? and how can i revert the migration from this? would i just call migrate:rollback to the path? – mdixon18 Jun 21 '16 at 21:02
  • 3
    @mdixon18 Rollbacks are potentially very nasty - I wouldn't automate that. [To my knowledge](http://stackoverflow.com/questions/30287896/rollback-one-specific-migration-in-laravel) there's no Artisan command to rollback a *specific* migration, so you might wind up rolling back the wrong one and blowing away data. I'd do the installation via an Artisan console command your app provides. – ceejayoz Jun 21 '16 at 21:09
  • I see, how would I load the package from say a controller outside of the package would I just name space in the provider class and call the installation method? -- what it does for config and views etc is that sufficient for a package to publish? – mdixon18 Jun 21 '16 at 21:17
3

After publishing the package:

php artisan vendor:publish --provider="Packages\Namespace\ServiceProvider"

You can execute the migration using:

php artisan migrate

Laravel automatically keeps track of which migrations have been executed and runs new ones accordingly.

If you want to execute the migration from outside of the CLI, for example in a route, you can do so using the Artisan facade:

Artisan::call('migrate')

You can pass optional parameters such as force and path as an array to the second argument in Artisan::call.

Further reading:

SArnab
  • 575
  • 3
  • 7
3

For the Laravel 7(and probably 6):

use Illuminate\Support\Facades\Artisan;


Artisan::call('migrate');

will greatly work.

Amin Shojaei
  • 5,451
  • 2
  • 38
  • 46
  • Is this process used to update(upgrade) the published project without data loss? – ufuk Jun 03 '20 at 11:36
  • 1
    @ufuk Migration will not harm your db or data by default. The `php artisan migrate` is a good command for update db of a published project. buy don't forget to get backup before running the migration. – Amin Shojaei Jun 03 '20 at 14:05
  • So normally, with the help of yes terminal, we can easily do it without losing data. But how will I apply this to my customer? Do you have any idea how to apply it to a database in Cpanel? – ufuk Jun 03 '20 at 19:48
  • 1
    @ufuk It's not a good approach to run migrations in the Cpanel. but you can write an endpoint and call the `migrate` command in the code. In Cpanel, people usually modifying the database manually. – Amin Shojaei Jun 03 '20 at 21:44
  • I understand but I will give the application to my customer. and I don't know his cpanel information. What way should I try to follow it so that it can upgrade the update. – ufuk Jun 04 '20 at 04:10
  • @ufuk What you mean? You don't have access to the customer's Cpanel? – Amin Shojaei Jun 04 '20 at 12:02