Skip to content

Commit 88e620a

Browse files
authored
Add contao:migrate command (#205)
1 parent e1f0f9f commit 88e620a

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

docs/dev/framework/migrations.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
---
2+
title: "Migrations"
3+
description: "Database migrations and general purpose migration scripts."
4+
---
5+
6+
{{% notice note %}}
7+
This covers the documentation on how to create migrations in Contao **4.9**
8+
and up. In previous Contao versions, migrations were written in `runonce.php` files that got deleted after execution.
9+
{{% /notice %}}
10+
11+
Updating Contao, extensions or the application itself sometimes requires to migrate data to be compatible with the new version(s). For this purpose Contao has a migration framework that lets you write migration services that are integrated in the update process.
12+
13+
The migrations get executed via the install tool database update or with the [`contao:migrate` command][commands].
14+
15+
16+
## Definition
17+
18+
To add a new migration, create a service that implements the interface `Contao\CoreBundle\Migration\MigrationInterface` and add the tag `contao.migration` (if autoconfiguration is enabled, this happens automatically):
19+
20+
```yaml
21+
# config/services.yaml
22+
services:
23+
App\Migration\MyMigration:
24+
tags:
25+
- { name: contao.migration, priority: 0 }
26+
```
27+
28+
## MigrationInterface
29+
30+
The migration interface specifies three methods that need to be implemented:
31+
32+
* __getName()__<br>
33+
A name that describes what the migration does. This text is shown to users when they are asked if they want to execute the migration.
34+
35+
* __shouldRun()__<br>
36+
This method checks if all prerequisites that are needed for the migration to run are met and if it actually needs to run. This method should be written very defensively because the application might be in an unexpected state when the method gets called, e.g. the database could be completely empty.
37+
38+
* __run()__<br>
39+
As the name suggests, that is where the real magic happens. If `shouldRun()` returned `true`, this method will be called and should do the actual migration.<br>
40+
It returns a `MigrationResult` object that can hold more information about what happened during the execution and if the migration was successful or not.<br>
41+
If something goes unexpectedly wrong here and you want to abort the migration process completeley you should throw an exception here.
42+
43+
44+
## Example
45+
46+
Lets say we have a database table `tl_customers` with a `firstName` and `lastName` column that we combined to a `name` column in the new version:
47+
48+
```php
49+
// src/Migration/CustomerNameMigration.php
50+
namespace App\Migration;
51+
52+
use Contao\CoreBundle\Migration\AbstractMigration;
53+
use Contao\CoreBundle\Migration\MigrationResult;
54+
use Doctrine\DBAL\Connection;
55+
56+
class CustomerNameMigration extends AbstractMigration
57+
{
58+
/**
59+
* @var Connection
60+
*/
61+
private $connection;
62+
63+
public function __construct(Connection $connection)
64+
{
65+
$this->connection = $connection;
66+
}
67+
68+
public function shouldRun(): bool
69+
{
70+
$schemaManager = $this->connection->getSchemaManager();
71+
72+
// If the database table itself does not exist we should do nothing
73+
if (!$schemaManager->tablesExist(['tl_customers'])) {
74+
return false;
75+
}
76+
77+
$columns = $schemaManager->listTableColumns('tl_customers');
78+
79+
return
80+
isset($columns['firstName']) &&
81+
isset($columns['lastName']) &&
82+
!isset($columns['name']);
83+
}
84+
85+
public function run(): MigrationResult
86+
{
87+
$this->connection->query('
88+
ALTER TABLE
89+
tl_customers
90+
ADD
91+
name varchar(255) NOT NULL DEFAULT '',
92+
');
93+
94+
$stmt = $this->connection->prepare('
95+
UPDATE
96+
tl_customers
97+
SET
98+
name = CONCAT(firstName, ' ', lastName)
99+
');
100+
101+
$stmt->execute();
102+
103+
return new MigrationResult(
104+
true,
105+
'Combined '. $stmt->rowCount().' customer names.'
106+
);
107+
}
108+
}
109+
```
110+
111+
112+
## Read more
113+
114+
* [Contao's console commands][commands]
115+
116+
117+
[commands]: /reference/commands/

docs/dev/reference/commands.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,25 @@ ask for it. The following tasks are available.
7171
| `generateInternalCache` | Warms up the internal cache. |
7272

7373

74+
## `contao:migrate`
75+
76+
{{< version "4.9" >}}
77+
78+
With this command you can execute migrations after an update of Contao or of an extension.
79+
The migrations that get executed are update scripts of Contao, registered migrations of
80+
extensions, legacy `runonce.php` files and the database update.
81+
82+
```sh
83+
$> php bin/console contao:migrate [options]
84+
```
85+
86+
| Option | Description |
87+
|--------------------|-------------|
88+
| `--with-deletes` | Executes all database migrations including `DROP` queries.|
89+
|`--schema-only` | Executes database schema migration only. Update scripts, registered migrations and `runonce.php` files get skipped.|
90+
| `--no-interaction` | With this option enabled all confirmation questions are automatically answered with “yes”. This is useful if you want to execute the migrations in an automated system.|
91+
92+
7493
## Other commands
7594

7695
* `contao:filesync`: Synchronises the file system to the database.

0 commit comments

Comments
 (0)