刚开始使用Propel 2.0 ORM。所有教程都告诉我们以这种方式使用模式:
$ propel model:build
如何在不使用命令行的情况下创建,重新创建或更新模型和数据,而只是在php脚本中?可能需要创建CMS模块安装程序或类似的东西。
答案 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();