如何使用命令行界面创建模型,表等

时间:2016-09-08 17:40:34

标签: php orm propel

刚开始使用Propel 2.0 ORM。所有教程都告诉我们以这种方式使用模式:

  1. 在XML / JSON / YAML / PHP文件中创建架构;
  2. 运行$ propel model:build
  3. 如何在不使用命令行的情况下创建,重新创建或更新模型和数据,而只是在php脚本中?可能需要创建CMS模块安装程序或类似的东西。

1 个答案:

答案 0 :(得分:0)

答案:指挥官班级

一种“重新发明轮子”的方法但我没有找到任何其他方法来使用没有CLI的Propel 2.

use Propel\Runtime\Propel;
use Propel\Generator\Command;

use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Application;

/**
 * Class Commander
 *
 * A script-based approach to run Propel commands without the CLI.
 *
 * Usage:
 *
 * ```
 * $cmd = new Commander('<propel_command>', '<command_arguments>');
 * $cmd->run();
 * ...
 * $cmd->addCommand('<propel_command>', '<command_arguments>');
 * $cmd->run();
 * ```
 *
 * In case of migration tasks you must call
 * ```
 * ...->preMigrate(array('<path_to_schema_files_dir1>', ..., '<path_to_schema_files_dirN>'), '<temp_dir>');
 * ```
 * to gather all schemas together and analyze 'em with propel:diff.
 *
 * Then after the diff and migrate are complete you must call ``postMigrate()`` to remove temporary
 * schema copies.
 *
 */
class Commander
{
    private $command,
            $parameters,
            $migrationTempSource;

    public function __construct($cmd = '', $params = '')
    {
        $this->addCommand($cmd, $params);
    }

    /**
     * Prepare schema files to be analyzed before the migration process.
     * @param array $schemaDirs Array of strings with schema directories
     * @param string $tmpSchemaDir Temporary directory to copy schemas to.
     * This path also must be used as a --schema-dir option value during the
     * diff and migrate tasks
     * @return boolean $result
     */
    public function preMigrate($schemaDirs = array(), $tmpSchemaDir)
    {
        $result = false;
        $filelist = [];
        foreach($schemaDirs as $path)
        {
            if(is_dir($path))
            {
                $f = $this->seekFiles($path);
                $filelist = count($f) > 0 ? array_merge($filelist, $f) : $f;
            }
        }
        if(!file_exists($tmpSchemaDir))
        {
            mkdir($tmpSchemaDir, 0777, true);
        }
        foreach($schemaDirs as $path)
        {
            if(is_dir($path))
            {
                $f = $this->seekFiles($path);
                foreach($f as $file)
                {
                    copy($path . '/' . $file, $tmpSchemaDir . '/' . $file);
                }
            }
        }
        $this->migrationTempSource = $tmpSchemaDir;
        return $result;
    }

    /**
     * Removes the temporary schema files after the diff and migrate tasks are complete.
     *
     * @param bool $removeTmpDir Set to true if you want to remove the whole temporary
     * directory, not just the schema files.
     * @return bool
     */
    public function postMigrate($removeTmpDir = false)
    {
        $result = false;
        $dir = scandir($this->migrationTempSource);
        foreach($dir as $d)
        {
            if($d != '.' && $d != '..')
            {
                unlink($this->migrationTempSource . '/' . $d);
            }
        }

        if($removeTmpDir === true)
        {
            @rmdir($this->migrationTempSource);
        }

        return $result;
    }

    private function seekFiles($dir)
    {
        $res = [];
        if(is_dir($dir))
        {
            $d = scandir($dir);
            foreach($d as $dd)
            {
                if($dd != '.' && $dd != '..')
                {
                    if((strpos($dd, 'schema.xml') == strlen($dd)-10) || ($dd == 'schema.xml'))
                    {
                        $res[] = $dd;
                    }
                }
            }
        }
        return $res;
    }

    public function addCommand($cmd = '', $params = '')
    {
        $this->command = $cmd;
        $this->parameters = explode(' --', $params);
    }

    public function run()
    {
        if($this->command == '') return false;

        $callCommandClass = '';
        $cmdParts = explode(':', $this->command);
        switch($cmdParts[0])
        {
            case 'config':
                switch($cmdParts[1])
                {
                    case 'convert':
                        $callCommandClass = 'ConfigConvertCommand';
                    break;
                }
            break;

            case 'diff':
                $callCommandClass = 'MigrationDiffCommand';
            break;

            case 'migration':
                switch($cmdParts[1])
                {
                    case 'create':
                        $callCommandClass = 'MigrationCreateCommand';
                    break;

                    case 'diff':
                        $callCommandClass = 'MigrationDiffCommand';
                    break;

                    case 'up':
                        $callCommandClass = 'MigrationUpCommand';
                    break;

                    case 'down':
                        $callCommandClass = 'MigrationDownCommand';
                    break;

                    case 'status':
                        $callCommandClass = 'MigrationStatusCommand';
                    break;

                    case 'migrate':
                        $callCommandClass = 'MigrationMigrateCommand';
                    break;
                }
            break;

            case 'model':
                switch($cmdParts[1])
                {
                    case 'build':
                        $callCommandClass = 'ModelBuildCommand';
                    break;
                }
            break;

            case 'sql':
                switch($cmdParts[1])
                {
                    case 'build':
                        $callCommandClass = 'SqlBuildCommand';
                    break;

                    case 'insert':
                        $callCommandClass = 'SqlInsertCommand';
                    break;
                }
            break;
        }

        $a = [];
        foreach($this->parameters as $p)
        {
            $x = explode('=', $p);
            if(count($x) > 1)
            {
                $a['--'.str_replace('--', '', $x[0])] = trim($x[1]);
            }
            else
            {
                $a['--'.str_replace('--', '', $x[0])] = true;
            }
        }

        $commandLine = array('command' => $this->command) + $a;

        $app = new Application('Propel', Propel::VERSION);
        $cls = '\Propel\Generator\Command'.'\\'.$callCommandClass;
        /** @noinspection PhpParamsInspection */
        $app->add(new $cls());
        $app->setAutoExit(false);
        $output = new StreamOutput(fopen("php://temp", 'r+'));
        $result = $app->run(new ArrayInput($commandLine), $output);

        if(0 !== $result)
        {
            rewind($output->getStream());
            return stream_get_contents($output->getStream());
        }
        else
        {
            return true;
        }
    }
}

用法示例:

//Convert the configuration file    
$cmd = new Commander('config:convert', '--config-dir='.$_SERVER['DOCUMENT_ROOT'].'/propeltest/config --output-dir='.$_SERVER['DOCUMENT_ROOT'].'/propeltest/config');
$cmd->run();

//... or (re)build models
$cmd = new Commander('model:build', '--schema-dir='.$_SERVER['DOCUMENT_ROOT'].'/propeltest/module/schema --output-dir='.$_SERVER['DOCUMENT_ROOT'].'/propeltest/module/models');
$cmd->run();

//... or perform database migration (actually not tested yet :/ )
$cmd = new Commander('migration:diff', '--schema-dir='.$_SERVER['DOCUMENT_ROOT'].'/propeltest/cache/schemacache');
$cmd->preMigrate([$_SERVER['DOCUMENT_ROOT'].'/propeltest/schema', $_SERVER['DOCUMENT_ROOT'].'/propeltest/module/schema'], $_SERVER['DOCUMENT_ROOT'].'/propeltest/cache/schemacache');
$cmd->run(); // runs migrate:diff
$cmd->addCommand('migration:diff', '--schema-dir='.$_SERVER['DOCUMENT_ROOT'].'/propeltest/cache/schemacache'); // prepare to actually migration
$cmd->run(); // perform migration:migrate
$cmd->postMigrate();