Skip to content

Commit b266816

Browse files
authored
Merge pull request #4 from moufmouf/quoteIdentifiers
Automatically quoting all identifiers
2 parents 6fb5fb3 + 3c6b943 commit b266816

File tree

7 files changed

+92
-13
lines changed

7 files changed

+92
-13
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,3 +200,24 @@ $db->table('users')
200200
```
201201

202202
The `extends` method will automatically create a primary key with the same name and same type as the extended table. It will also make sure this primary key is a foreign key pointing to the extended table.
203+
204+
## Automatic 'quoting' of table and column names
205+
206+
By default, the fluid-schema-builder will **not** quote your identifiers (because it does not know what database you use).
207+
208+
This means that you cannot create an item with a reserved keyword.
209+
210+
```php
211+
$db->table('contacts')
212+
->id()
213+
->column('date')->datetime(); // Will most likely fail, because "date" is a reserved keyword!
214+
```
215+
216+
However, if you give to *fluid-schema-builder* your database platform at build time, then it **will quote all identifiers by default**. No more nasty surprises!
217+
218+
```php
219+
use TheCodingMachine\FluidSchema\DefaultNamingStrategy;
220+
221+
// Assuming $connection is your DBAL connection
222+
$db = new FluidSchema($schema, new DefaultNamingStrategy($connection->getDatabasePlatform()));
223+
```

src/DefaultNamingStrategy.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,20 @@
44
namespace TheCodingMachine\FluidSchema;
55

66
use Doctrine\Common\Inflector\Inflector;
7+
use Doctrine\DBAL\Platforms\AbstractPlatform;
78

89
class DefaultNamingStrategy implements NamingStrategyInterface
910
{
11+
/**
12+
* @var AbstractPlatform
13+
*/
14+
private $platform;
15+
16+
public function __construct(AbstractPlatform $platform = null)
17+
{
18+
$this->platform = $platform;
19+
}
20+
1021
/**
1122
* Returns the name of the jointure table from the name of the joined tables.
1223
*
@@ -48,4 +59,15 @@ private function toSingular($plural): string
4859

4960
return implode('_', $strs);
5061
}
62+
63+
/**
64+
* Let's quote if a database platform has been provided to us!
65+
*
66+
* @param string $identifier
67+
* @return string
68+
*/
69+
public function quoteIdentifier(string $identifier): string
70+
{
71+
return ($this->platform !== null) ? $this->platform->quoteIdentifier($identifier) : $identifier;
72+
}
5173
}

src/FluidColumn.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ class FluidColumn
2525
* @var Table
2626
*/
2727
private $table;
28+
/**
29+
* @var NamingStrategyInterface
30+
*/
31+
private $namingStrategy;
2832

2933
/**
3034
* FluidColumn constructor.
@@ -33,12 +37,13 @@ class FluidColumn
3337
* @param Table $table
3438
* @param Column $column
3539
*/
36-
public function __construct(FluidSchema $fluidSchema, FluidTable $fluidTable, Table $table, Column $column)
40+
public function __construct(FluidSchema $fluidSchema, FluidTable $fluidTable, Table $table, Column $column, NamingStrategyInterface $namingStrategy)
3741
{
3842
$this->fluidSchema = $fluidSchema;
3943
$this->fluidTable = $fluidTable;
4044
$this->column = $column;
4145
$this->table = $table;
46+
$this->namingStrategy = $namingStrategy;
4247
}
4348

4449
public function integer(): FluidColumnOptions
@@ -208,6 +213,8 @@ public function object(): FluidColumnOptions
208213

209214
public function references(string $tableName, ?string $constraintName = null, string $onUpdate = 'RESTRICT', string $onDelete = 'RESTRICT'): FluidColumnOptions
210215
{
216+
$tableName = $this->namingStrategy->quoteIdentifier($tableName);
217+
211218
$table = $this->fluidSchema->getDbalSchema()->getTable($tableName);
212219

213220
$referencedColumns = $table->getPrimaryKeyColumns();
@@ -216,7 +223,7 @@ public function references(string $tableName, ?string $constraintName = null, st
216223
throw new FluidSchemaException('You cannot reference a table with a primary key on several columns using FluidSchema. Use DBAL Schema methods instead.');
217224
}
218225

219-
$referencedColumnName = $referencedColumns[0];
226+
$referencedColumnName = $this->namingStrategy->quoteIdentifier($referencedColumns[0]);
220227
$referencedColumn = $table->getColumn($referencedColumnName);
221228

222229
$this->column->setType($referencedColumn->getType());
@@ -226,7 +233,7 @@ public function references(string $tableName, ?string $constraintName = null, st
226233
$this->column->setPrecision($referencedColumn->getPrecision());
227234
$this->column->setUnsigned($referencedColumn->getUnsigned());
228235

229-
$this->table->addForeignKeyConstraint($table, [$this->column->getName()], $referencedColumns, [
236+
$this->table->addForeignKeyConstraint($table, [$this->namingStrategy->quoteIdentifier($this->column->getName())], $referencedColumns, [
230237
'onUpdate' => $onUpdate,
231238
'onDelete' => $onDelete
232239
], $constraintName);
@@ -235,6 +242,6 @@ public function references(string $tableName, ?string $constraintName = null, st
235242

236243
private function getOptions(): FluidColumnOptions
237244
{
238-
return new FluidColumnOptions($this->fluidTable, $this->column);
245+
return new FluidColumnOptions($this->fluidTable, $this->column, $this->namingStrategy);
239246
}
240247
}

src/FluidColumnOptions.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,21 @@ class FluidColumnOptions
1616
* @var Column
1717
*/
1818
private $column;
19+
/**
20+
* @var NamingStrategyInterface
21+
*/
22+
private $namingStrategy;
1923

2024
/**
2125
* FluidColumn constructor.
2226
* @param FluidTable $fluidTable
2327
* @param Column $column
2428
*/
25-
public function __construct(FluidTable $fluidTable, Column $column)
29+
public function __construct(FluidTable $fluidTable, Column $column, NamingStrategyInterface $namingStrategy)
2630
{
2731
$this->fluidTable = $fluidTable;
2832
$this->column = $column;
33+
$this->namingStrategy = $namingStrategy;
2934
}
3035

3136
/**
@@ -66,7 +71,7 @@ public function unique(): FluidColumnOptions
6671
*/
6772
public function index(): FluidColumnOptions
6873
{
69-
$this->fluidTable->index([$this->column->getName()]);
74+
$this->fluidTable->index([$this->namingStrategy->quoteIdentifier($this->column->getName())]);
7075
return $this;
7176
}
7277
public function comment(string $comment): FluidColumnOptions
@@ -85,7 +90,7 @@ public function primaryKey(?string $indexName = null): FluidColumnOptions
8590
{
8691
$newIndexName = $indexName ?: false;
8792

88-
$this->fluidTable->primaryKey([$this->column->getName()], $newIndexName);
93+
$this->fluidTable->primaryKey([$this->namingStrategy->quoteIdentifier($this->column->getName())], $newIndexName);
8994
return $this;
9095
}
9196

src/FluidSchema.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public function __construct(Schema $schema, ?NamingStrategyInterface $namingStra
3434

3535
public function table(string $name): FluidTable
3636
{
37+
$name = $this->namingStrategy->quoteIdentifier($name);
38+
3739
if (isset($this->fluidTables[$name])) {
3840
return $this->fluidTables[$name];
3941
}
@@ -44,7 +46,7 @@ public function table(string $name): FluidTable
4446
$table = $this->schema->createTable($name);
4547
}
4648

47-
$this->fluidTables[$name] = new FluidTable($this, $table);
49+
$this->fluidTables[$name] = new FluidTable($this, $table, $this->namingStrategy);
4850
return $this->fluidTables[$name];
4951
}
5052

src/FluidTable.php

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,26 @@ class FluidTable
1919
* @var FluidColumn[]
2020
*/
2121
private $fluidColumns;
22+
/**
23+
* @var NamingStrategyInterface
24+
*/
25+
private $namingStrategy;
2226

2327
/**
2428
* @param FluidSchema $schema
2529
* @param Table $table
2630
*/
27-
public function __construct(FluidSchema $schema, Table $table)
31+
public function __construct(FluidSchema $schema, Table $table, NamingStrategyInterface $namingStrategy)
2832
{
2933
$this->schema = $schema;
3034
$this->table = $table;
35+
$this->namingStrategy = $namingStrategy;
3136
}
3237

3338
public function column(string $name): FluidColumn
3439
{
40+
$name = $this->namingStrategy->quoteIdentifier($name);
41+
3542
if (isset($this->fluidColumns[$name])) {
3643
return $this->fluidColumns[$name];
3744
}
@@ -42,30 +49,35 @@ public function column(string $name): FluidColumn
4249
$column = $this->table->addColumn($name, 'string');
4350
}
4451

45-
$this->fluidColumns[$name] = new FluidColumn($this->schema, $this, $this->table, $column);
52+
$this->fluidColumns[$name] = new FluidColumn($this->schema, $this, $this->table, $column, $this->namingStrategy);
4653
return $this->fluidColumns[$name];
4754
}
4855

4956
public function index(array $columnNames): FluidTable
5057
{
51-
$this->table->addIndex($columnNames);
58+
$this->table->addIndex($this->quoteArray($columnNames));
5259
return $this;
5360
}
5461

5562
public function unique(array $columnNames): FluidTable
5663
{
57-
$this->table->addUniqueIndex($columnNames);
64+
$this->table->addUniqueIndex($this->quoteArray($columnNames));
5865
return $this;
5966
}
6067

6168
public function primaryKey(array $columnNames, ?string $indexName = null): FluidTable
6269
{
6370
$newIndexName = $indexName ?: false;
6471

65-
$this->table->setPrimaryKey($columnNames, $newIndexName);
72+
$this->table->setPrimaryKey($this->quoteArray($columnNames), $newIndexName);
6673
return $this;
6774
}
6875

76+
private function quoteArray(array $columnNames): array
77+
{
78+
return array_map([$this->namingStrategy, 'quoteIdentifier'], $columnNames);
79+
}
80+
6981
/**
7082
* Creates a "id" autoincremented primary key column.
7183
*
@@ -102,6 +114,8 @@ public function timestamps(): FluidTable
102114

103115
public function extends(string $tableName): FluidTable
104116
{
117+
$tableName = $this->namingStrategy->quoteIdentifier($tableName);
118+
105119
$inheritedTable = $this->schema->getDbalSchema()->getTable($tableName);
106120

107121
$pks = $inheritedTable->getPrimaryKeyColumns();

src/NamingStrategyInterface.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,12 @@ public function getJointureTableName(string $table1, string $table2): string;
2020
* @return string
2121
*/
2222
public function getForeignKeyColumnName(string $targetTable): string;
23+
24+
/**
25+
* Decides to quote an identifier (or not) and returns the result.
26+
*
27+
* @param string $identifier
28+
* @return string
29+
*/
30+
public function quoteIdentifier(string $identifier): string;
2331
}

0 commit comments

Comments
 (0)