Laravel 在包中注册种子

问题描述 投票:0回答:4

我正在开发一个包,它创建多个迁移,我想播种。然后还有一些其他子包,它们也可以使用种子创建迁移。所以周围可能有很多种子,我不想强迫用户向 DatabaseSeeder 添加数十行。

类似

php artisan db:seed --class="MyNamespace\\DatabaseSeeder"
的东西可以工作,但这样用户就无法使用相同的命令进行迁移和播种,因为
php artisan migrate --seed
不接受类选项。

基本上,我正在寻找类似于

loadMigrationsFrom()
类的
ServiceProvider
的东西。

如有任何帮助,我们将不胜感激。

更新:我主要对 Laravel 5.3 的解决方案感兴趣,我会以某种方式找出向后兼容性

php laravel laravel-5
4个回答
6
投票

这也适用于“db:seed”命令和“--seed”选项。

了解更多信息:https://github.com/wowcee/laravel-seeds-service-provider

<?php

namespace Core\Providers;

use Illuminate\Console\Events\CommandFinished;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\ServiceProvider;
use Symfony\Component\Console\Output\ConsoleOutput;

class SeedServiceProvider extends ServiceProvider
{
    protected $seeds_path = '/../database/seeds';


    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        if ($this->app->runningInConsole()) {
            if ($this->isConsoleCommandContains([ 'db:seed', '--seed' ], [ '--class', 'help', '-h' ])) {
                $this->addSeedsAfterConsoleCommandFinished();
            }
        }
    }

    /**
     * Get a value that indicates whether the current command in console
     * contains a string in the specified $fields.
     *
     * @param string|array $contain_options
     * @param string|array $exclude_options
     *
     * @return bool
     */
    protected function isConsoleCommandContains($contain_options, $exclude_options = null) : bool
    {
        $args = Request::server('argv', null);
        if (is_array($args)) {
            $command = implode(' ', $args);
            if (str_contains($command, $contain_options) && ($exclude_options == null || !str_contains($command, $exclude_options))) {
                return true;
            }
        }
        return false;
    }

    /**
     * Add seeds from the $seed_path after the current command in console finished.
     */
    protected function addSeedsAfterConsoleCommandFinished()
    {
        Event::listen(CommandFinished::class, function(CommandFinished $event) {
            // Accept command in console only,
            // exclude all commands from Artisan::call() method.
            if ($event->output instanceof ConsoleOutput) {
                $this->addSeedsFrom(__DIR__ . $this->seeds_path);
            }
        });
    }

    /**
     * Register seeds.
     *
     * @param string  $seeds_path
     * @return void
     */
    protected function addSeedsFrom($seeds_path)
    {
        $file_names = glob( $seeds_path . '/*.php');
        foreach ($file_names as $filename)
        {
            $classes = $this->getClassesFromFile($filename);
            foreach ($classes as $class) {
                Artisan::call('db:seed', [ '--class' => $class, '--force' => '' ]);
            }
        }
    }

    /**
     * Get full class names declared in the specified file.
     *
     * @param string $filename
     * @return array an array of class names.
     */
    private function getClassesFromFile(string $filename) : array
    {
        // Get namespace of class (if vary)
        $namespace = "";
        $lines = file($filename);
        $namespaceLines = preg_grep('/^namespace /', $lines);
        if (is_array($namespaceLines)) {
            $namespaceLine = array_shift($namespaceLines);
            $match = array();
            preg_match('/^namespace (.*);$/', $namespaceLine, $match);
            $namespace = array_pop($match);
        }

        // Get name of all class has in the file.
        $classes = array();
        $php_code = file_get_contents($filename);
        $tokens = token_get_all($php_code);
        $count = count($tokens);
        for ($i = 2; $i < $count; $i++) {
            if ($tokens[$i - 2][0] == T_CLASS && $tokens[$i - 1][0] == T_WHITESPACE && $tokens[$i][0] == T_STRING) {
                $class_name = $tokens[$i][1];
                if ($namespace !== "") {
                    $classes[] = $namespace . "\\$class_name";
                } else {
                    $classes[] = $class_name;
                }
            }
        }

        return $classes;
    }
}

5
投票

找不到以正确顺序加载、包含文件并执行它们的本机函数。方法虽简陋,但有效。 migrate:refresh --seed 不适用于此方法,因为它假设服务提供程序运行时存在表,但 db:seed 却存在。

                protected function registerSeedsFrom($path)
                {
                    foreach (glob("$path/*.php") as $filename)
                    {
                        include $filename;
                        $classes = get_declared_classes();
                        $class = end($classes);

                        $command = Request::server('argv', null);
                        if (is_array($command)) {
                            $command = implode(' ', $command);
                            if ($command == "artisan db:seed") {
                                Artisan::call('db:seed', ['--class' => $class]);
                            }
                        }

                    }
                }

在启动方法中与自定义服务提供者/包一起使用:

    if ($this->app->runningInConsole()) {
        $this->registerMigrations();
        $this->registerEloquentFactoriesFrom(__DIR__.'/../database/factories');
        $this->registerSeedsFrom(__DIR__.'/../database/seeds');

}


1
投票
 php artisan db:seed --class="Package\Name\database\seeds\NameTableSeeder"

0
投票

文件“应用程序/演示/数据库/迁移/Table_DemoTypes.php”:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up()
    {
        Schema::disableForeignKeyConstraints();
        Schema::create('demo_types', function (Blueprint $table) {
            $table->id('id');
            $table->integer('f_integer');
        });

        if (\App::runningInConsole()) {
            $args = Request::server('argv', null);
            if (is_array($args) && array_intersect($args, ['db:seed', '--seed'])) {
                Artisan::call('db:seed', ['--class' => 'App\\Demo\\Database\\Seeders\\Seeder_DemoRelation']);
            }
        }
    }

    public function down()
    {
        Schema::dropIfExists('demo_types');
    }
};

文件“应用程序/演示/数据库/Seeders/Seeder_DemoTypes.php”:

namespace App\Demo\Database\Seeders;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Seeder;

class Seeder_DemoTypes extends Seeder
{
    public function run()
    {
        if (Schema::hasTable('demo_types')) {
            DB::transaction(function () {
                DB::table('demo_types')->insert(['f_integer' => 1]);
                DB::table('demo_types')->insert(['f_integer' => 2]);
                DB::table('demo_types')->insert(['f_integer' => 3]);
            });
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.