修复seeder错误;删除第三方的think迁移工具,在extend中重新实现;

This commit is contained in:
2023-09-20 15:35:20 +08:00
parent 0b23e0a940
commit 85f2f29b81
91 changed files with 20798 additions and 66 deletions

View File

@@ -0,0 +1,338 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Migration;
use Cake\Database\Query;
use Phinx\Db\Adapter\AdapterInterface;
use Phinx\Db\Table;
use RuntimeException;
use think\console\Input as InputInterface;
use think\console\Output as OutputInterface;
/**
* Abstract Migration Class.
*
* It is expected that the migrations you write extend from this class.
*
* This abstract class proxies the various database methods to your specified
* adapter.
*
* @author Rob Morgan <robbym@gmail.com>
*/
abstract class AbstractMigration implements MigrationInterface
{
/**
* @var string
*/
protected $environment;
/**
* @var int
*/
protected $version;
/**
* @var \Phinx\Db\Adapter\AdapterInterface|null
*/
protected $adapter;
/**
* @var \think\console\Output|null
*/
protected $output;
/**
* @var \think\console\Input|null
*/
protected $input;
/**
* Whether this migration is being applied or reverted
*
* @var bool
*/
protected $isMigratingUp = true;
/**
* List of all the table objects created by this migration
*
* @var array<\Phinx\Db\Table>
*/
protected $tables = [];
/**
* @param string $environment Environment Detected
* @param int $version Migration Version
* @param \think\console\Input|null $input Input
* @param \think\console\Output|null $output Output
*/
final public function __construct(string $environment, int $version, ?InputInterface $input = null, ?OutputInterface $output = null)
{
$this->environment = $environment;
$this->version = $version;
if ($input !== null) {
$this->setInput($input);
}
if ($output !== null) {
$this->setOutput($output);
}
}
/**
* @inheritDoc
*/
public function setAdapter(AdapterInterface $adapter): MigrationInterface
{
$this->adapter = $adapter;
return $this;
}
/**
* @inheritDoc
*/
public function getAdapter(): ?AdapterInterface
{
return $this->adapter;
}
/**
* @inheritDoc
*/
public function setInput(InputInterface $input): MigrationInterface
{
$this->input = $input;
return $this;
}
/**
* @inheritDoc
*/
public function getInput(): ?InputInterface
{
return $this->input;
}
/**
* @inheritDoc
*/
public function setOutput(OutputInterface $output): MigrationInterface
{
$this->output = $output;
return $this;
}
/**
* @inheritDoc
*/
public function getOutput(): ?OutputInterface
{
return $this->output;
}
/**
* @inheritDoc
*/
public function getName(): string
{
return static::class;
}
/**
* @inheritDoc
*/
public function getEnvironment(): string
{
return $this->environment;
}
/**
* @inheritDoc
*/
public function setVersion($version): MigrationInterface
{
$this->version = $version;
return $this;
}
/**
* @inheritDoc
*/
public function getVersion(): int
{
return $this->version;
}
/**
* @inheritDoc
*/
public function setMigratingUp(bool $isMigratingUp): MigrationInterface
{
$this->isMigratingUp = $isMigratingUp;
return $this;
}
/**
* @inheritDoc
*/
public function isMigratingUp(): bool
{
return $this->isMigratingUp;
}
/**
* @inheritDoc
*/
public function execute(string $sql, array $params = []): int
{
return $this->getAdapter()->execute($sql, $params);
}
/**
* @inheritDoc
*/
public function query(string $sql, array $params = [])
{
return $this->getAdapter()->query($sql, $params);
}
/**
* @inheritDoc
*/
public function getQueryBuilder(): Query
{
return $this->getAdapter()->getQueryBuilder();
}
/**
* @inheritDoc
*/
public function fetchRow(string $sql)
{
return $this->getAdapter()->fetchRow($sql);
}
/**
* @inheritDoc
*/
public function fetchAll(string $sql): array
{
return $this->getAdapter()->fetchAll($sql);
}
/**
* @inheritDoc
*/
public function createDatabase(string $name, array $options): void
{
$this->getAdapter()->createDatabase($name, $options);
}
/**
* @inheritDoc
*/
public function dropDatabase(string $name): void
{
$this->getAdapter()->dropDatabase($name);
}
/**
* @inheritDoc
*/
public function createSchema(string $name): void
{
$this->getAdapter()->createSchema($name);
}
/**
* @inheritDoc
*/
public function dropSchema(string $name): void
{
$this->getAdapter()->dropSchema($name);
}
/**
* @inheritDoc
*/
public function hasTable(string $tableName): bool
{
return $this->getAdapter()->hasTable($tableName);
}
/**
* @inheritDoc
*/
public function table(string $tableName, array $options = []): Table
{
$table = new Table($tableName, $options, $this->getAdapter());
$this->tables[] = $table;
return $table;
}
/**
* Perform checks on the migration, print a warning
* if there are potential problems.
*
* Right now, the only check is if there is both a `change()` and
* an `up()` or a `down()` method.
*
* @return void
*/
public function preFlightCheck(): void
{
if (method_exists($this, MigrationInterface::CHANGE)) {
if (
method_exists($this, MigrationInterface::UP) ||
method_exists($this, MigrationInterface::DOWN)
) {
$this->output->writeln(sprintf(
'<comment>warning</comment> Migration contains both change() and up()/down() methods. <options=bold>Ignoring up() and down()</>.'
));
}
}
}
/**
* Perform checks on the migration after completion
*
* Right now, the only check is whether all changes were committed
*
* @throws \RuntimeException
* @return void
*/
public function postFlightCheck(): void
{
foreach ($this->tables as $table) {
if ($table->hasPendingActions()) {
throw new RuntimeException('Migration has pending actions after execution!');
}
}
}
/**
* Checks to see if the migration should be executed.
*
* Returns true by default.
*
* You can use this to prevent a migration from executing.
*
* @return bool
*/
public function shouldExecute(): bool
{
return true;
}
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Migration;
use think\console\Input as InputInterface;
use think\console\Output as OutputInterface;
abstract class AbstractTemplateCreation implements CreationInterface
{
/**
* @var \think\console\Input
*/
protected $input;
/**
* @var \think\console\Output
*/
protected $output;
/**
* @param \think\console\Input|null $input Input
* @param \think\console\Output|null $output Output
*/
public function __construct(?InputInterface $input = null, ?OutputInterface $output = null)
{
if ($input !== null) {
$this->setInput($input);
}
if ($output !== null) {
$this->setOutput($output);
}
}
/**
* @inheritDoc
*/
public function getInput(): InputInterface
{
return $this->input;
}
/**
* @inheritDoc
*/
public function setInput(InputInterface $input): CreationInterface
{
$this->input = $input;
return $this;
}
/**
* @inheritDoc
*/
public function getOutput(): OutputInterface
{
return $this->output;
}
/**
* @inheritDoc
*/
public function setOutput(OutputInterface $output): CreationInterface
{
$this->output = $output;
return $this;
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Migration;
use think\console\Input as InputInterface;
use think\console\Output as OutputInterface;
/**
* Migration interface
*
* @author Richard Quadling <RQuadling@GMail.com>
*/
interface CreationInterface
{
/**
* @param \think\console\Input|null $input Input
* @param \think\console\Output|null $output Output
*/
public function __construct(?InputInterface $input = null, ?OutputInterface $output = null);
/**
* @param \think\console\Input $input Input
* @return $this
*/
public function setInput(InputInterface $input);
/**
* @param \think\console\Output $output Output
* @return $this
*/
public function setOutput(OutputInterface $output);
/**
* @return \think\console\Input
*/
public function getInput(): InputInterface;
/**
* @return \think\console\Output
*/
public function getOutput(): OutputInterface;
/**
* Get the migration template.
*
* This will be the content that Phinx will amend to generate the migration file.
*
* @return string The content of the template for Phinx to amend.
*/
public function getMigrationTemplate(): string;
/**
* Post Migration Creation.
*
* Once the migration file has been created, this method will be called, allowing any additional
* processing, specific to the template to be performed.
*
* @param string $migrationFilename The name of the newly created migration.
* @param string $className The class name.
* @param string $baseClassName The name of the base class.
* @return void
*/
public function postMigrationCreation(string $migrationFilename, string $className, string $baseClassName): void;
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Migration;
use Exception;
/**
* Exception class thrown when migrations cannot be reversed using the 'change'
* feature.
*
* @author Rob Morgan <robbym@gmail.com>
*/
class IrreversibleMigrationException extends Exception
{
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,398 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Migration\Manager;
use PDO;
use Phinx\Db\Adapter\AdapterFactory;
use Phinx\Db\Adapter\AdapterInterface;
use Phinx\Migration\MigrationInterface;
use Phinx\Seed\SeedInterface;
use RuntimeException;
use think\console\Input as InputInterface;
use think\console\Output as OutputInterface;
class Environment
{
/**
* @var string
*/
protected $name;
/**
* @var array<string, mixed>
*/
protected $options;
/**
* @var \think\console\Input|null
*/
protected $input;
/**
* @var \think\console\Output|null
*/
protected $output;
/**
* @var int
*/
protected $currentVersion;
/**
* @var string
*/
protected $schemaTableName = 'phinxlog';
/**
* @var \Phinx\Db\Adapter\AdapterInterface
*/
protected $adapter;
/**
* @param string $name Environment Name
* @param array<string, mixed> $options Options
*/
public function __construct(string $name, array $options)
{
$this->name = $name;
$this->options = $options;
}
/**
* Executes the specified migration on this environment.
*
* @param \Phinx\Migration\MigrationInterface $migration Migration
* @param string $direction Direction
* @param bool $fake flag that if true, we just record running the migration, but not actually do the migration
* @return void
*/
public function executeMigration(MigrationInterface $migration, string $direction = MigrationInterface::UP, bool $fake = false): void
{
$direction = $direction === MigrationInterface::UP ? MigrationInterface::UP : MigrationInterface::DOWN;
$migration->setMigratingUp($direction === MigrationInterface::UP);
$startTime = time();
$migration->setAdapter($this->getAdapter());
$migration->preFlightCheck();
if (method_exists($migration, MigrationInterface::INIT)) {
$migration->{MigrationInterface::INIT}();
}
if (!$fake) {
// begin the transaction if the adapter supports it
if ($this->getAdapter()->hasTransactions()) {
$this->getAdapter()->beginTransaction();
}
// Run the migration
if (method_exists($migration, MigrationInterface::CHANGE)) {
if ($direction === MigrationInterface::DOWN) {
// Create an instance of the ProxyAdapter so we can record all
// of the migration commands for reverse playback
/** @var \Phinx\Db\Adapter\ProxyAdapter $proxyAdapter */
$proxyAdapter = AdapterFactory::instance()
->getWrapper('proxy', $this->getAdapter());
$migration->setAdapter($proxyAdapter);
$migration->{MigrationInterface::CHANGE}();
$proxyAdapter->executeInvertedCommands();
$migration->setAdapter($this->getAdapter());
} else {
$migration->{MigrationInterface::CHANGE}();
}
} else {
$migration->{$direction}();
}
// commit the transaction if the adapter supports it
if ($this->getAdapter()->hasTransactions()) {
$this->getAdapter()->commitTransaction();
}
}
$migration->postFlightCheck();
// Record it in the database
$this->getAdapter()->migrated($migration, $direction, date('Y-m-d H:i:s', $startTime), date('Y-m-d H:i:s', time()));
}
/**
* Executes the specified seeder on this environment.
*
* @param \Phinx\Seed\SeedInterface $seed Seed
* @return void
*/
public function executeSeed(SeedInterface $seed): void
{
$seed->setAdapter($this->getAdapter());
if (method_exists($seed, SeedInterface::INIT)) {
$seed->{SeedInterface::INIT}();
}
// begin the transaction if the adapter supports it
if ($this->getAdapter()->hasTransactions()) {
$this->getAdapter()->beginTransaction();
}
// Run the seeder
if (method_exists($seed, SeedInterface::RUN)) {
$seed->{SeedInterface::RUN}();
}
// commit the transaction if the adapter supports it
if ($this->getAdapter()->hasTransactions()) {
$this->getAdapter()->commitTransaction();
}
}
/**
* Sets the environment's name.
*
* @param string $name Environment Name
* @return $this
*/
public function setName(string $name)
{
$this->name = $name;
return $this;
}
/**
* Gets the environment name.
*
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* Sets the environment's options.
*
* @param array<string, mixed> $options Environment Options
* @return $this
*/
public function setOptions(array $options)
{
$this->options = $options;
return $this;
}
/**
* Gets the environment's options.
*
* @return array<string, mixed>
*/
public function getOptions(): array
{
return $this->options;
}
/**
* Sets the console input.
*
* @param \think\console\Input $input Input
* @return $this
*/
public function setInput(InputInterface $input)
{
$this->input = $input;
return $this;
}
/**
* Gets the console input.
*
* @return \think\console\Input|null
*/
public function getInput(): ?InputInterface
{
return $this->input;
}
/**
* Sets the console output.
*
* @param \think\console\Output $output Output
* @return $this
*/
public function setOutput(OutputInterface $output)
{
$this->output = $output;
return $this;
}
/**
* Gets the console output.
*
* @return \think\console\Output|null
*/
public function getOutput(): ?OutputInterface
{
return $this->output;
}
/**
* Gets all migrated version numbers.
*
* @return array
*/
public function getVersions(): array
{
return $this->getAdapter()->getVersions();
}
/**
* Get all migration log entries, indexed by version creation time and sorted in ascending order by the configuration's
* version_order option
*
* @return array
*/
public function getVersionLog(): array
{
return $this->getAdapter()->getVersionLog();
}
/**
* Sets the current version of the environment.
*
* @param int $version Environment Version
* @return $this
*/
public function setCurrentVersion(int $version)
{
$this->currentVersion = $version;
return $this;
}
/**
* Gets the current version of the environment.
*
* @return int
*/
public function getCurrentVersion(): int
{
// We don't cache this code as the current version is pretty volatile.
// that means they're no point in a setter then?
// maybe we should cache and call a reset() method every time a migration is run
$versions = $this->getVersions();
$version = 0;
if (!empty($versions)) {
$version = end($versions);
}
$this->setCurrentVersion($version);
return $this->currentVersion;
}
/**
* Sets the database adapter.
*
* @param \Phinx\Db\Adapter\AdapterInterface $adapter Database Adapter
* @return $this
*/
public function setAdapter(AdapterInterface $adapter)
{
$this->adapter = $adapter;
return $this;
}
/**
* Gets the database adapter.
*
* @throws \RuntimeException
* @return \Phinx\Db\Adapter\AdapterInterface
*/
public function getAdapter(): AdapterInterface
{
if (isset($this->adapter)) {
return $this->adapter;
}
$options = $this->getOptions();
if (isset($options['connection'])) {
if (!($options['connection'] instanceof PDO)) {
throw new RuntimeException('The specified connection is not a PDO instance');
}
$options['connection']->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$options['adapter'] = $options['connection']->getAttribute(PDO::ATTR_DRIVER_NAME);
}
if (!isset($options['adapter'])) {
throw new RuntimeException('No adapter was specified for environment: ' . $this->getName());
}
$factory = AdapterFactory::instance();
$adapter = $factory
->getAdapter($options['adapter'], $options);
// Automatically time the executed commands
$adapter = $factory->getWrapper('timed', $adapter);
if (isset($options['wrapper'])) {
$adapter = $factory
->getWrapper($options['wrapper'], $adapter);
}
/** @var \think\console\Input|null $input */
$input = $this->getInput();
if ($input) {
$adapter->setInput($this->getInput());
}
/** @var \think\console\Output|null $output */
$output = $this->getOutput();
if ($output) {
$adapter->setOutput($this->getOutput());
}
// Use the TablePrefixAdapter if table prefix/suffixes are in use
if ($adapter->hasOption('table_prefix') || $adapter->hasOption('table_suffix')) {
$adapter = AdapterFactory::instance()
->getWrapper('prefix', $adapter);
}
$this->setAdapter($adapter);
return $adapter;
}
/**
* Sets the schema table name.
*
* @param string $schemaTableName Schema Table Name
* @return $this
*/
public function setSchemaTableName($schemaTableName)
{
$this->schemaTableName = $schemaTableName;
return $this;
}
/**
* Gets the schema table name.
*
* @return string
*/
public function getSchemaTableName(): string
{
return $this->schemaTableName;
}
}

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
$namespaceDefinition
use $useClassName;
final class $className extends $baseClassName
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change(): void
{
}
}

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
$namespaceDefinition
use $useClassName;
final class $className extends $baseClassName
{
public function up(): void
{
}
public function down(): void
{
}
}

View File

@@ -0,0 +1,269 @@
<?php
/**
* MIT License
* For full license information, please view the LICENSE file that was distributed with this source code.
*/
namespace Phinx\Migration;
use Cake\Database\Query;
use Phinx\Db\Adapter\AdapterInterface;
use Phinx\Db\Table;
use think\console\Input as InputInterface;
use think\console\Output as OutputInterface;
/**
* Migration interface
*
* @author Rob Morgan <robbym@gmail.com>
*/
interface MigrationInterface
{
/**
* @var string
*/
public const CHANGE = 'change';
/**
* @var string
*/
public const UP = 'up';
/**
* @var string
*/
public const DOWN = 'down';
/**
* @var string
*/
public const INIT = 'init';
/**
* Sets the database adapter.
*
* @param \Phinx\Db\Adapter\AdapterInterface $adapter Database Adapter
* @return $this
*/
public function setAdapter(AdapterInterface $adapter);
/**
* Gets the database adapter.
*
* @return \Phinx\Db\Adapter\AdapterInterface|null
*/
public function getAdapter(): ?AdapterInterface;
/**
* Sets the input object to be used in migration object
*
* @param \think\console\Input $input Input
* @return $this
*/
public function setInput(InputInterface $input);
/**
* Gets the input object to be used in migration object
*
* @return \think\console\Input|null
*/
public function getInput(): ?InputInterface;
/**
* Sets the output object to be used in migration object
*
* @param \think\console\Output $output Output
* @return $this
*/
public function setOutput(OutputInterface $output);
/**
* Gets the output object to be used in migration object
*
* @return \think\console\Output|null
*/
public function getOutput(): ?OutputInterface;
/**
* Gets the name.
*
* @return string
*/
public function getName(): string;
/**
* Gets the detected environment
*
* @return string
*/
public function getEnvironment(): string;
/**
* Sets the migration version number.
*
* @param int $version Version
* @return $this
*/
public function setVersion(int $version);
/**
* Gets the migration version number.
*
* @return int
*/
public function getVersion(): int;
/**
* Sets whether this migration is being applied or reverted
*
* @param bool $isMigratingUp True if the migration is being applied
* @return $this
*/
public function setMigratingUp(bool $isMigratingUp);
/**
* Gets whether this migration is being applied or reverted.
* True means that the migration is being applied.
*
* @return bool
*/
public function isMigratingUp(): bool;
/**
* Executes a SQL statement and returns the number of affected rows.
*
* @param string $sql SQL
* @param array $params parameters to use for prepared query
* @return int
*/
public function execute(string $sql, array $params = []): int;
/**
* Executes a SQL statement.
*
* The return type depends on the underlying adapter being used. To improve
* IDE auto-completion possibility, you can overwrite the query method
* phpDoc in your (typically custom abstract parent) migration class, where
* you can set the return type by the adapter in your current use.
*
* @param string $sql SQL
* @param array $params parameters to use for prepared query
* @return mixed
*/
public function query(string $sql, array $params = []);
/**
* Returns a new Query object that can be used to build complex SELECT, UPDATE, INSERT or DELETE
* queries and execute them against the current database.
*
* Queries executed through the query builder are always sent to the database, regardless of the
* the dry-run settings.
*
* @see https://api.cakephp.org/3.6/class-Cake.Database.Query.html
* @return \Cake\Database\Query
*/
public function getQueryBuilder(): Query;
/**
* Executes a query and returns only one row as an array.
*
* @param string $sql SQL
* @return array|false
*/
public function fetchRow(string $sql);
/**
* Executes a query and returns an array of rows.
*
* @param string $sql SQL
* @return array
*/
public function fetchAll(string $sql): array;
/**
* Create a new database.
*
* @param string $name Database Name
* @param array<string, mixed> $options Options
* @return void
*/
public function createDatabase(string $name, array $options): void;
/**
* Drop a database.
*
* @param string $name Database Name
* @return void
*/
public function dropDatabase(string $name): void;
/**
* Creates schema.
*
* This will thrown an error for adapters that do not support schemas.
*
* @param string $name Schema name
* @return void
* @throws \BadMethodCallException
*/
public function createSchema(string $name): void;
/**
* Drops schema.
*
* This will thrown an error for adapters that do not support schemas.
*
* @param string $name Schema name
* @return void
* @throws \BadMethodCallException
*/
public function dropSchema(string $name): void;
/**
* Checks to see if a table exists.
*
* @param string $tableName Table name
* @return bool
*/
public function hasTable(string $tableName): bool;
/**
* Returns an instance of the <code>\Table</code> class.
*
* You can use this class to create and manipulate tables.
*
* @param string $tableName Table name
* @param array<string, mixed> $options Options
* @return \Phinx\Db\Table
*/
public function table(string $tableName, array $options): Table;
/**
* Perform checks on the migration, printing a warning
* if there are potential problems.
*
* @return void
*/
public function preFlightCheck(): void;
/**
* Perform checks on the migration after completion
*
* Right now, the only check is whether all changes were committed
*
* @return void
*/
public function postFlightCheck(): void;
/**
* Checks to see if the migration should be executed.
*
* Returns true by default.
*
* You can use this to prevent a migration from executing.
*
* @return bool
*/
public function shouldExecute(): bool;
}