# SchemaTool: Create Table IF NOT EXISTS

**URL:** <https://forum.shopware.com/t/schematool-create-table-if-not-exists/43450>\
**Category:** Programmierung\
**Created:** [6. Februar 2017 um 12:54 UTC](https://forum.shopware.com/t/schematool-create-table-if-not-exists/43450 "2017-02-06T12:54:05Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Synonymous](https://avatars.discourse-cdn.com/v4/letter/s/57b2e6/32.png) [@Synonymous](https://forum.shopware.com/u/Synonymous)\
**Post date:** [6. Februar 2017 um 12:54 UTC](https://forum.shopware.com/t/schematool-create-table-if-not-exists/43450/1 "2017-02-06T12:54:05Z")

</div>

Hallo,

Kennt Ihr einen Weg das SchemaTool so zu nützen, dass **Tabellen nur neu angelegt werden, wenn Sie noch nicht existieren**?

```
    /**
     * Creates the schemas for the additional models
     */
    public static function createSchemas()
    {
        $tool = new SchemaTool(Shopware()->Container()->get('models'));
        $classes = [
            Shopware()->Container()->get('models')->getClassMetadata(Discount::class),
            Shopware()->Container()->get('models')->getClassMetadata(AccessCode::class)
        ];
        $tool->createSchema($classes);
    }

```

Wenn ich die Tabellen beim Uninstall nicht löschen möchte führt das beim erneuten Install des Plugins aktuell zu einer Exception.  
Eine $tool-\>hasTable() Methode oder einen entsprechenden Parameter beim Anlegen habe ich bislang leider nicht gefunden.

Kennt ihr hier einen Weg?

Danke & liebe Grüße

---

<div class="post-metadata">

**Author:** ![alexxxbing](https://avatars.discourse-cdn.com/v4/letter/a/898d66/32.png) [@alexxxbing](https://forum.shopware.com/u/alexxxbing)\
**Post date:** [9. Februar 2017 um 08:27 UTC](https://forum.shopware.com/t/schematool-create-table-if-not-exists/43450/2 "2017-02-09T08:27:33Z")

</div>

Versuch erstmal die Klassen zu löschen und dann zu erzeugen.

```
$tool->dropSchema($classes);
$tool->createSchema($classes);

```

&nbsp;

---

<div class="post-metadata">

**Author:** ![pwagner](https://avatars.discourse-cdn.com/v4/letter/p/9e8a1a/32.png) [@pwagner](https://forum.shopware.com/u/pwagner)\
**Post date:** [9. Februar 2017 um 08:47 UTC](https://forum.shopware.com/t/schematool-create-table-if-not-exists/43450/3 "2017-02-09T08:47:02Z")

</div>

Durch dropSchema würde der Table gelöscht werden, was Synonymous vermutlich auch bei der Installation&nbsp;nicht möchte („Wenn ich die Tabellen beim Uninstall nicht löschen möchte…“).  
Ich habe ebenfalls ein Plugin, dessen Daten ich nicht verlieren möchte, wenn das Plugin deinstalliert oder neuinstalliert wird.

Ich habe das derzeit so gelöst, dass ich bei der Installation eine eigene PDO Connection öffne und das „CREATE TABLE IF NOT EXISTS“ statement absetze.&nbsp;  
Falls es einen bessere&nbsp;Lösung dafür&nbsp;gibt, wäre ich für Feedback dankbar.

---

<div class="post-metadata">

**Author:** ![kcon](https://avatars.discourse-cdn.com/v4/letter/k/ed655f/32.png) [@kcon](https://forum.shopware.com/u/kcon)\
**Post date:** [9. Februar 2017 um 09:50 UTC](https://forum.shopware.com/t/schematool-create-table-if-not-exists/43450/4 "2017-02-09T09:50:37Z")

</div>

Hallo Synonymous,

der `SchemaManager` von Doctrine bietet die Methode `tablesExist(array $tableNames)` (siehe: [http://www.doctrine-project.org/api/dbal/2.4/class-Doctrine.DBAL.Schema.AbstractSchemaManager.html#\_tablesExist](http://www.doctrine-project.org/api/dbal/2.4/class-Doctrine.DBAL.Schema.AbstractSchemaManager.html#_tablesExist) ).

Deine Methode könnte damit in etwa so aussehen (ungetestet):

```
/**
 * Creates the schemas for the additional models
 */
public static function createSchemas() {
    $tool = new SchemaTool(Shopware()->Container()->get('models'));
    $classes = [
        Shopware()->Container()->get('models')->getClassMetadata(Discount::class),
        Shopware()->Container()->get('models')->getClassMetadata(AccessCode::class)
    ];

    // you could (and should) also implement a method which dynamically returns an array of
    // table names based on the ClassMetadata in $classes
    $tableNames = array("table1", "table2");

    $schemaManager = Shopware()->Container()->get('models')->getConnection()->getSchemaManager();
    if (!$schemaManager->tablesExist($tableNames)) {
        $tool->createSchema($classes);
    }
}

```

Viele Grüße

---

<div class="post-metadata">

**Author:** ![alexxxbing](https://avatars.discourse-cdn.com/v4/letter/a/898d66/32.png) [@alexxxbing](https://forum.shopware.com/u/alexxxbing)\
**Post date:** [9. Februar 2017 um 12:23 UTC](https://forum.shopware.com/t/schematool-create-table-if-not-exists/43450/5 "2017-02-09T12:23:30Z")

</div>

@pwagner du hast rechts, habe das nicht gelesen :D.

> [@kcon schrieb:](https://forum.shopware.com/profile/22055/kcon "kcon")
> 
> Hallo Synonymous,
> 
> der `SchemaManager` von Doctrine bietet die Methode `tablesExist(array $tableNames)` (siehe: [http://www.doctrine-project.org/api/dbal/2.4/class-Doctrine.DBAL.Schema.AbstractSchemaManager.html#\_tablesExist](http://www.doctrine-project.org/api/dbal/2.4/class-Doctrine.DBAL.Schema.AbstractSchemaManager.html#_tablesExist) ).
> 
> Deine Methode könnte damit in etwa so aussehen (ungetestet):
> 
> /\*\*
> 
> - Creates the schemas for the additional models  
> \*/  
> public static function createSchemas() {  
> $tool = new SchemaTool(Shopware()-\>Container()-\>get(‚models‘));  
> $classes = [  
> Shopware()-\>Container()-\>get(‚models‘)-\>getClassMetadata(Discount::class),  
> Shopware()-\>Container()-\>get(‚models‘)-\>getClassMetadata(AccessCode::class)  
> ];
> 
> // you could (and should) also implement a method which dynamically returns an array of  
> // table names based on the ClassMetadata in $classes  
> $tableNames = array(„table1“, „table2“);
> 
> $schemaManager = Shopware()-\>Container()-\>get(‚models‘)-\>getConnection()-\>getSchemaManager();  
> if (!$schemaManager-\>tablesExist($tableNames)) {  
> $tool-\>createSchema($classes);  
> }  
> }
> 
> Viele Grüße

&nbsp;Man braucht vlt. eine Mischung von createSchema mit updateSchema. Wenn in der Zwischen eine neue Version des Plugins gibt, würde diese Funktion nicht mehr richtig funktionieren.

Deine Methode könnte damit in etwa so aussehen (ungetestet):

```
/**
 * Creates the schemas for the additional models
 */
public static function createSchemas() {
    $tool = new SchemaTool(Shopware()->Container()->get('models'));
    $tables = [
        "table1" => Shopware()->Container()->get('models')->getClassMetadata(Discount::class),
        "table2" => Shopware()->Container()->get('models')->getClassMetadata(AccessCode::class)
    ];

    $schemaManager = Shopware()->Container()->get('models')->getConnection()->getSchemaManager();
    foreach($tables as $tableName => $class){

    
      if (!$schemaManager->tablesExist($tableName)) {
          $tool->createSchema([$class]);
      }else{
          $tool->updateSchema([$class], true); //true - saveMode and not delete other schemas
      }
    }
}

```

&nbsp;

---

<div class="post-metadata">

**Author:** ![Synonymous](https://avatars.discourse-cdn.com/v4/letter/s/57b2e6/32.png) [@Synonymous](https://forum.shopware.com/u/Synonymous)\
**Post date:** [10. Februar 2017 um 09:07 UTC](https://forum.shopware.com/t/schematool-create-table-if-not-exists/43450/6 "2017-02-10T09:07:23Z")

</div>

Guten Morgen zusammen,

Eine ifTableExists Methode habe ich eigentlich gesucht. Die gibt es in meiner Version des SchemaTools (Doctrine\ORM\Tools) aber leider nicht!? 🙂

Möglicherweise gibt es die in einer anderen Doctrine Version - in jener die bei Shopware genutzt wird fehlt sie aber. Oder ich bin gerade völlig am falschen Dampfer…

Liebe Grüße

---

<div class="post-metadata">

**Author:** ![kcon](https://avatars.discourse-cdn.com/v4/letter/k/ed655f/32.png) [@kcon](https://forum.shopware.com/u/kcon)\
**Post date:** [10. Februar 2017 um 09:18 UTC](https://forum.shopware.com/t/schematool-create-table-if-not-exists/43450/7 "2017-02-10T09:18:55Z")

</div>

> [@Synonymous schrieb:](https://forum.shopware.com/profile/24210/Synonymous "Synonymous")
> 
> Eine ifTableExists Methode habe ich eigentlich gesucht. Die gibt es in meiner Version des SchemaTools (Doctrine\ORM\Tools) aber leider nicht!?

Das ist richtig, denn die Methode heißt&nbsp; `tablesExist` statt `ifTableExists` und ist im `SchemaManager` anstatt des `SchemaTools` implementiert.

Deswegen auch die Zeile

```
$schemaManager = Shopware()->Container()->get('models')->getConnection()->getSchemaManager();

```

Ansonsten tut sie aus meiner Sicht genau das, wonach Du gesucht hast: Man kann damit vor dem Erstellen von Schemata prüfen, ob die Tabellennamen schon existieren.

Viele Grüße

---

<div class="post-metadata">

**Author:** ![Synonymous](https://avatars.discourse-cdn.com/v4/letter/s/57b2e6/32.png) [@Synonymous](https://forum.shopware.com/u/Synonymous)\
**Post date:** [10. Februar 2017 um 13:59 UTC](https://forum.shopware.com/t/schematool-create-table-if-not-exists/43450/8 "2017-02-10T13:59:30Z")

</div>

Alles klar… hatte nicht gesehen, dass Du den Manager statt den Tools heranziehst…  
Danke, werde ich gleich mal so umsetzen. ![Thumb-Up](https://europe1.discourse-cdn.com/flex013/uploads/shopware/original/1X/7fcda44f782696668a3d093569d15e88105769e1.png "Thumb-Up")

---

<div class="post-metadata">

**Author:** ![andres](https://avatars.discourse-cdn.com/v4/letter/a/a4c791/32.png) [@andres](https://forum.shopware.com/u/andres)\
**Post date:** [31. August 2018 um 12:13 UTC](https://forum.shopware.com/t/schematool-create-table-if-not-exists/43450/9 "2018-08-31T12:13:12Z")

</div>

Vielen Dank für eure Ideen @kcon und @alexxxbing. Mit “getTableName” kann man sich einfach den Tabellennamen aus der Klasse holen und muss diesen nicht manuell im Installer hinterlegen:

```
    private function createSchema()
    {
        $tool = new SchemaTool($this->modelManager);
        $classes = [
            $this->modelManager->getClassMetadata(Confirmation::class),
            $this->modelManager->getClassMetadata(Shipment::class),
            $this->modelManager->getClassMetadata(ShipmentDetail::class),
            $this->modelManager->getClassMetadata(StockList::class)
        ];

        /** @var \Doctrine\DBAL\Schema\AbstractSchemaManager $schemaManager */
        $schemaManager = $this->modelManager->getConnection()->getSchemaManager();

        /** @var \Doctrine\ORM\Mapping\ClassMetadata $class */
        foreach ($classes as $class) {
            if (!$schemaManager->tablesExist([$class->getTableName()])) {
                $tool->createSchema([$class]);
            } else {
                $tool->updateSchema([$class], true); //true - saveMode and not delete other schemas
            }
        }
    }

```

&nbsp;
