Laravel在包装中注册种子

时间:2016-10-17 21:14:47

标签: laravel laravel-5

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

.apk之类的内容可行,但这样用户无法使用相同的命令进行迁移和播种,因为php artisan db:seed --class="MyNamespace\\DatabaseSeeder"不接受类选项。

基本上,我正在寻找与php artisan migrate --seed类的loadMigrationsFrom()类似的内容。

任何帮助都将不胜感激。

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

3 个答案:

答案 0 :(得分:2)

无法找到以正确顺序加载的本机函数,包含文件并执行它们。方法很粗糙,但有效。 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 :(得分:0)

该功能适用​​于“ 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;
    }
}

答案 2 :(得分:0)

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