Laravel 5 动态运行迁移

11

所以我已经在 Packages/Sitemanager/Blog 的结构中创建了自己的博客包,我有一个服务提供者看起来像下面这样:

所以我已经在Packages/Sitemanager/Blog的结构中创建了自己的博客包,我有一个类似于以下内容的服务提供者:

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';
    }
}
现在,我想要做的是,在安装过程中或者从未运行过迁移时动态地运行迁移。我曾经在旧文档中看到过可以这样做的例子:
Artisan::call('migrate', array('--path' => 'app/migrations'));

然而,在laravel 5中,这是无效的,我该如何处理?


https://laravel.com/docs/5.2/artisan#calling-commands-via-code - Marcin Orlowski
3个回答

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

在Laravel 5中可以使用,但是您可能需要进行一些调整。

首先,在文件顶部(与use Illuminate\Support\ServiceProvider...处)需要添加use Artisan;行,因为 Laravel 5具有命名空间。您还可以使用\Artisan::call - \很重要).

您可能还需要执行以下操作:

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

--force参数是必须的,因为在生产环境中,默认情况下Laravel会提示您进行yes/no确认,因为这是一个潜在具有破坏性的命令。如果没有--force参数,则您的代码将一直处于等待状态(Laravel正在等待CLI的响应,但您不在CLI中)。

enter image description here

我建议您在服务提供者的boot方法之外执行此操作。这些可能会造成很大的负担(依赖于文件系统和数据库调用,您不希望在每个页面视图上都进行调用)。考虑使用显式的安装控制台命令或路由代替。


现在我正在使用我的引导命令,但我可能会考虑在安装后运行某种安装命令(目前不确定最佳方法)。无论如何,执行 \Artisan::call('migrate', array('--path' => 'packages/sitemanager/blog/migrations', '--force' => true)); 对我有用,我可以看到对数据库所做的更改。你会如何进行安装过程?我该如何还原此迁移?只需调用 migrate:rollback 到路径吗? - mdixon18
3
回滚可能非常麻烦 - 我不会自动化处理它。据我所知,在 Laravel 中没有 Artisan 命令可以回滚“特定”的迁移,因此您可能会回滚错误的内容并且删掉数据。我建议您通过应用程序提供的 Artisan 控制台命令来进行安装。 - ceejayoz
我明白了,如果我想从包外面的控制器加载包,我只需要在提供者类中定义名称空间并调用安装方法吗?对于配置和视图等方面所做的工作是否足以发布包? - mdixon18

3
发布包后,您可以执行以下命令来执行迁移: php artisan migrate Laravel会自动跟踪已经执行的迁移并相应地运行新的迁移。
如果您想在CLI之外执行迁移,例如在路由中,您可以使用Artisan门面这样做: Artisan::call('migrate') 您可以将可选参数(如force和path)作为数组传递给Artisan :: call的第二个参数。
进一步阅读:

3

对于 Laravel 7(也适用于 Laravel 6):

use Illuminate\Support\Facades\Artisan;


Artisan::call('migrate');

将极大地发挥作用。


这个过程是否用于更新(升级)已发布的项目而不会丢失数据? - ufuk
1
@ufuk 迁移默认情况下不会损坏你的数据库或数据。php artisan migrate 是更新已发布项目数据库的良好命令。但在运行迁移之前,请不要忘记备份。 - Amin Shojaei
通常情况下,借助终端的帮助,我们可以轻松地完成此操作而不会丢失数据。但是我该如何将其应用于我的客户?您有任何想法如何将其应用于Cpanel中的数据库吗? - ufuk
1
@ufuk 在Cpanel中运行迁移并不是一个好的方法。但您可以编写一个端点(endpoint),在代码中调用“migrate”命令。在Cpanel中,人们通常手动修改数据库。 - Amin Shojaei
我理解,但是我会把应用程序交给我的客户。我不知道他的cpanel信息。我应该尝试哪种方式来升级更新呢? - ufuk
@ufuk 你的意思是什么?你没有访问客户的Cpanel的权限吗? - Amin Shojaei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接