php Doctrine(和Migrations)DBA

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php Doctrine(和Migrations)DBA相关的知识,希望对你有一定的参考价值。

// Чтобы создать миграцию нужно выполнить в консоли
php migrations.phar migrations:generate

// Чтобы накатить все миграции
php migrations.phar migrations:migrate

// Иногда нужно накатить миграцию, проверить, что-то поменять и снова накатить
// Можно сходить в БД и удалить из таблицы migration_versions нужную версию
// А можно в самой миграции описать удаление версии сраз

// БОЛЬШЕ НЕ РАБОТАЕТ - используем php migrations.phar migrations:prev
/*public function postUp(Schema $schema) {
		$current_version = preg_replace("/[^0-9]/", '', get_class($this));
		$qb = $this->connection->createQueryBuilder();
		$qb
			->delete('migration_versions')
			->where('version = :version')
			->setParameter(':version', $current_version);
		if ($qb->execute()) $this->write("\r\nTHE MIGRATION SIGN HAS BEEN REMOVED");
}*/

// Вывести что-то в консоль можно так

public function up(Schema $schema) {
		$this->write('JSON ENCODE IS FINISH!');
		$this->write('UPDATE TABLE...');
}

// Стандартный пример миграции
// -> Пример со вставкой столбца следующим за service_comments
public function up(Schema $schema) {
    $this->addSql("
		SET NAMES 'utf8';
	  ALTER TABLE cars ADD COLUMN contractor_currencies_id TINYINT(4) UNSIGNED DEFAULT 1 COMMENT 'Валюта поставщика' AFTER service_comments;
	  ");
}

public function down(Schema $schema) {
	  $this->addSql("
	  ALTER TABLE cars DROP contractor_currencies_id;
	  ");
}

// -> Пример с созданием таблицы
public function up(Schema $schema) {
		$this->addSql("
		SET NAMES 'utf8';
		CREATE TABLE approvals_transmitted (
			id INT(11) NOT NULL AUTO_INCREMENT,
			parent_approval_id INT(11) NOT NULL COMMENT 'Идентификатор родительской схемы утверждения, которая передает свои данные',
			parent_company_id INT(11) UNSIGNED NOT NULL COMMENT 'Идентификатор родительской компании, которая передает схему утверждения',
			child_approval_id INT(11) NOT NULL COMMENT 'Идентификатор дочерней схемы утверждения, которая принимает данные',
			child_company_id INT(11) UNSIGNED NOT NULL COMMENT 'Идентификатор дочерней компании, которая принимает схему утверждения',
			PRIMARY KEY (id),
			INDEX FK_parent_approval_id (parent_approval_id),
			INDEX FK_parent_company_id (parent_company_id),
			INDEX FK_child_approval_id (child_approval_id),
			INDEX FK_child_company_id (child_company_id),
      CONSTRAINT FK_parent_approval_id FOREIGN KEY (parent_approval_id) REFERENCES approvals (id),
			CONSTRAINT FK_parent_company_id FOREIGN KEY (parent_company_id) REFERENCES company (id),
			CONSTRAINT FK_child_approval_id FOREIGN KEY (child_approval_id) REFERENCES approvals (id),
			CONSTRAINT FK_child_company_id FOREIGN KEY (child_company_id) REFERENCES company (id)
		)
		COMMENT='Содержит связи между схемами утверждений, если они были транслированы'
		COLLATE='utf8_unicode_ci'
		ENGINE=InnoDB;
	  ");
}

public function down(Schema $schema) {
		$this->addSql("
		SET NAMES 'utf8';
	  DROP TABLE approvals_transmitted;
	  ");
}

// Если нужны множественные вставки или апдейты, то у меня получилось только через $this->addSql()
// Заодно описан метод preUp(), он выполняется до up()
// В этом методе используется QueryBuilder

public $toJsonResult = array(); // Выносим свойство в класс

public function preUp(Schema $schema): void {

		$qb = $this->connection->createQueryBuilder();
		$qb
			->select('hnsd.id')
			->addSelect('hnsd.synonyms')
			->addSelect('hnsd.street_synonyms')
			->from('hotel_names_synonyms_dict', 'hnsd');

		$query = $qb->execute();
		$result = $query->fetchAll();

		for ($i = 0; $i < count($result); $i++) {
			$synonyms = explode(';', $result[$i]['synonyms']);
			$street_synonyms = explode(';', $result[$i]['street_synonyms']);
			$id = $result[$i]['id'];
			$this->toJsonResult[] = array(
				'synonyms' => json_encode($synonyms, JSON_UNESCAPED_UNICODE),
				'street_synonyms' => json_encode($street_synonyms, JSON_UNESCAPED_UNICODE),
				'id' => $id,
			);
		}
}

public function up(Schema $schema) {
      foreach ($this->toJsonResult as $res) {
			  $this->addSql('UPDATE hotel_names_synonyms_dict SET synonyms = :synonyms, street_synonyms = :street_synonyms WHERE id = :id', $res);
		  }
}

// Не проверял, но говорят вот так тоже можно
$qb = $this->connection
           ->createQueryBuilder(
            "SELECT a FROM tbl a WHERE a.name = :name")
           ->setParameter('name',$name);
$qb->getQuery()->execute();

// Возможно пригодятся (не проверял)
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
// А вообще вот тут описана работа с миграциями в симфонии https://www.sgalinski.de/typo3-agentur/technik/how-to-work-with-doctrine-migrations-in-symfony/

// Вот тут можно смотреть методы для QueryBuilder
https://www.doctrine-project.org/api/dbal/2.7/Doctrine/DBAL/Driver/ResultStatement.html
https://www.doctrine-project.org/projects/doctrine-migrations/en/latest/reference/migration-classes.html#methods-to-call
https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/query-builder.html#working-with-querybuilder
https://www.doctrine-project.org/projects/doctrine-migrations/en/1.7/reference/migration_classes.html

// Можно щелкнуть в коде по методу QueryBuilder (например, delete) и перейти к реализации. Там в комментах есть пример ))

// Пример обновления с несколькими подготовленными выражениями

$qb = $this->connection->createQueryBuilder();
$qb
	->update('hotel_names_synonyms_dict', 'hnsd')
	->set('hnsd.synonyms', ':synonyms')
	->set('hnsd.street_synonyms', ':street_synonyms')
	->where('id', ':id')
	->setParameter(':synonyms', $i)
	->setParameter(':street_synonyms', $i)
	->setParameter(':id', $arr[$i]['id']);
$qb->execute();

// Посмотрим статус
php migrations.phar migrations:status

// Откат миграций
// Идем в БД таблицу migration_versions
// Выбираем нужную версию (например предыдущую) и выполняем
php migrations.phar migrations:migrate 20181009130715

// Повторно накатить миграцию
// Идем в БД таблицу migration_versions
// Выбираем нужную версию и удаляем её из таблицы
// Вновь выполняем миграцию в терминале

$result = $query->fetchAll() // array(0 => array('column' => 'data', ...), 1 => array('column' => 'data2, ...), 2 => ...)
$result = $query->fetch(); // array('column' => 'data', ...)
$result = $query->fetchColumn(); // data
	
// Плейсхолдеры
->where('g.name = :name')
->setParameter('name', $name)
----
->where('u.id', '?1'),
->where('u.id', '?2'),
->setParameter(1, 123);
->setParameter(2, 321);
----
->setParameters(array('param1'=> $param1, 'param2' => $param2))
----
->where('at.id_service = :id_service AND at.ticketnum = :ticketnum')
->setParameter('id_service', '1038367')
->setParameter('ticketnum', '5552647029402');

// Пример группировки в запросе
'SELECT partial u.{id, username}, partial a.{id, name} FROM CmsUser u JOIN u.articles a'
	

以上是关于php Doctrine(和Migrations)DBA的主要内容,如果未能解决你的问题,请参考以下文章

如何阻止 Doctrine2 Migrations:Diff 总是添加数据库中已经存在的外键关系?

[Doctrine Migrations] 数据库迁移组件的深入解析四:集成diff方式迁移组件

无法在 Symfony 4.1 项目中安装 Doctrine Migrations V2

[Doctrine Migrations] 数据库迁移组件的深入解析一:安装与使用

Symfony 3.4没有元数据类来处理错误

Symfony 2.4.2 作曲家迁移包