Completed
Branch feature/pre-split (406cca)
by Anton
08:47
created

AbstractTable::resetState()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\Database\Schemas\Prototypes;
8
9
use Interop\Container\ContainerInterface;
10
use Psr\Log\LoggerAwareInterface;
11
use Spiral\Core\Component;
12
use Spiral\Database\Entities\Driver;
13
use Spiral\Database\Exceptions\SchemaException;
14
use Spiral\Database\Schemas\ColumnInterface;
15
use Spiral\Database\Schemas\IndexInterface;
16
use Spiral\Database\Schemas\ReferenceInterface;
17
use Spiral\Database\Schemas\StateComparator;
18
use Spiral\Database\Schemas\TableInterface;
19
use Spiral\Database\Schemas\TableState;
20
use Spiral\Debug\Traits\LoggerTrait;
21
22
/**
23
 * AbstractTable class used to describe and manage state of specified table. It provides ability to
24
 * get table introspection, update table schema and automatically generate set of diff operations.
25
 *
26
 * Most of table operation like column, index or foreign key creation/altering will be applied when
27
 * save() method will be called.
28
 *
29
 * Column configuration shortcuts:
30
 *
31
 * @method AbstractColumn primary($column)
32
 * @method AbstractColumn bigPrimary($column)
33
 * @method AbstractColumn enum($column, array $values)
34
 * @method AbstractColumn string($column, $length = 255)
35
 * @method AbstractColumn decimal($column, $precision, $scale)
36
 * @method AbstractColumn boolean($column)
37
 * @method AbstractColumn integer($column)
38
 * @method AbstractColumn tinyInteger($column)
39
 * @method AbstractColumn bigInteger($column)
40
 * @method AbstractColumn text($column)
41
 * @method AbstractColumn tinyText($column)
42
 * @method AbstractColumn longText($column)
43
 * @method AbstractColumn double($column)
44
 * @method AbstractColumn float($column)
45
 * @method AbstractColumn datetime($column)
46
 * @method AbstractColumn date($column)
47
 * @method AbstractColumn time($column)
48
 * @method AbstractColumn timestamp($column)
49
 * @method AbstractColumn binary($column)
50
 * @method AbstractColumn tinyBinary($column)
51
 * @method AbstractColumn longBinary($column)
52
 */
53
abstract class AbstractTable extends Component implements TableInterface, LoggerAwareInterface
54
{
55
    use LoggerTrait;
56
57
    /**
58
     * Indication that table is exists and current schema is fetched from database.
59
     *
60
     * @var bool
61
     */
62
    private $exists = false;
63
64
    /**
65
     * Database specific tablePrefix. Required for table renames.
66
     *
67
     * @var string
68
     */
69
    private $prefix = '';
70
71
    /**
72
     * @invisible
73
     *
74
     * @var Driver
75
     */
76
    protected $driver = null;
77
78
    /**
79
     * Initial table state.
80
     *
81
     * @invisible
82
     * @var TableState
83
     */
84
    protected $initialState = null;
85
86
    /**
87
     * Currently defined table state.
88
     *
89
     * @invisible
90
     * @var TableState
91
     */
92
    protected $currentState = null;
93
94
    /**
95
     * @param Driver $driver Parent driver.
96
     * @param string $name   Table name, must include table prefix.
97
     * @param string $prefix Database specific table prefix.
98
     */
99
    public function __construct(Driver $driver, string $name, string $prefix)
100
    {
101
        $this->driver = $driver;
102
        $this->prefix = $prefix;
103
104
        //Initializing states
105
        $this->initialState = new TableState($this->prefix . $name);
106
        $this->currentState = new TableState($this->prefix . $name);
107
108
        $this->exists = $this->driver->hasTable($this->getName());
109
110
        if ($this->exists) {
111
            //Initiating table schema
112
            $this->initSchema($this->initialState);
113
        }
114
115
        $this->setState($this->initialState);
116
    }
117
118
    /**
119
     * Get instance of associated driver.
120
     *
121
     * @return Driver
122
     */
123
    public function getDriver(): Driver
124
    {
125
        return $this->driver;
126
    }
127
128
    /**
129
     * @return StateComparator
130
     */
131
    public function getComparator(): StateComparator
132
    {
133
        return new StateComparator($this->initialState, $this->currentState);
134
    }
135
136
    /**
137
     * Check if table schema has been modified since synchronization.
138
     *
139
     * @return bool
140
     */
141
    protected function hasChanges(): bool
142
    {
143
        return $this->getComparator()->hasChanges();
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149
    public function exists(): bool
150
    {
151
        return $this->exists;
152
    }
153
154
    /**
155
     * Return database specific table prefix.
156
     *
157
     * @return string
158
     */
159
    public function getPrefix(): string
160
    {
161
        return $this->prefix;
162
    }
163
164
    /**
165
     * Sets table name. Use this function in combination with save to rename table.
166
     *
167
     * @param string $name
168
     *
169
     * @return string Prefixed table name.
170
     */
171
    public function setName(string $name): string
172
    {
173
        $this->currentState->setName($this->prefix . $name);
174
175
        return $this->getName();
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public function getName(): string
182
    {
183
        return $this->currentState->getName();
184
    }
185
186
    /**
187
     * Set table primary keys. Operation can only be applied for newly created tables. Now every
188
     * database might support compound indexes.
189
     *
190
     * @param array $columns
191
     *
192
     * @return self
193
     */
194
    public function setPrimaryKeys(array $columns): AbstractTable
195
    {
196
        //Originally we were forcing an exception when primary key were changed, now we should
197
        //force it when table will be synced
198
199
        //Updating primary keys in current state
200
        $this->currentState->setPrimaryKeys($columns);
201
202
        return $this;
203
    }
204
205
    /**
206
     * {@inheritdoc}
207
     */
208
    public function getPrimaryKeys(): array
209
    {
210
        return $this->currentState->getPrimaryKeys();
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     */
216
    public function hasColumn(string $name): bool
217
    {
218
        return $this->currentState->hasColumn($name);
219
    }
220
221
    /**
222
     * {@inheritdoc}
223
     *
224
     * @return ColumnInterface[]|AbstractColumn[]
225
     */
226
    public function getColumns(): array
227
    {
228
        return $this->currentState->getColumns();
229
    }
230
231
    /**
232
     * {@inheritdoc}
233
     */
234
    public function hasIndex(array $columns = []): bool
235
    {
236
        return $this->currentState->hasIndex($columns);
237
    }
238
239
    /**
240
     * {@inheritdoc}
241
     *
242
     * @return IndexInterface[]|AbstractIndex[]
243
     */
244
    public function getIndexes(): array
245
    {
246
        return $this->currentState->getIndexes();
247
    }
248
249
    /**
250
     * {@inheritdoc}
251
     */
252
    public function hasForeign(string $column): bool
253
    {
254
        return $this->currentState->hasForeign($column);
255
    }
256
257
    /**
258
     * {@inheritdoc}
259
     *
260
     * @return ReferenceInterface[]|AbstractReference[]
261
     */
262
    public function getForeigns(): array
263
    {
264
        return $this->currentState->getForeigns();
265
    }
266
267
    /**
268
     * {@inheritdoc}
269
     */
270
    public function getDependencies(): array
271
    {
272
        $tables = [];
273
        foreach ($this->currentState->getForeigns() as $foreign) {
274
            $tables[] = $foreign->getForeignTable();
275
        }
276
277
        return $tables;
278
    }
279
280
    /**
281
     * Get/create instance of AbstractColumn associated with current table.
282
     *
283
     * Examples:
284
     * $table->column('name')->string();
285
     *
286
     * @param string $name
287
     *
288
     * @return AbstractColumn
289
     */
290
    public function column(string $name): AbstractColumn
291
    {
292
        if ($this->currentState->hasColumn($name)) {
293
            //Column already exists
294
            return $this->currentState->findColumn($name);
295
        }
296
297
        $column = $this->createColumn($name);
298
        $this->currentState->registerColumn($column);
299
300
        return $column;
301
    }
302
303
    /**
304
     * Shortcut for column() method.
305
     *
306
     * @param string $column
307
     *
308
     * @return AbstractColumn
309
     */
310
    public function __get(string $column)
311
    {
312
        return $this->column($column);
313
    }
314
315
    /**
316
     * Column creation/altering shortcut, call chain is identical to:
317
     * AbstractTable->column($name)->$type($arguments).
318
     *
319
     * Example:
320
     * $table->string("name");
321
     * $table->text("some_column");
322
     *
323
     * @param string $type
324
     * @param array  $arguments Type specific parameters.
325
     *
326
     * @return AbstractColumn
327
     */
328
    public function __call(string $type, array $arguments)
329
    {
330
        return call_user_func_array(
331
            [$this->column($arguments[0]), $type],
332
            array_slice($arguments, 1)
333
        );
334
    }
335
336
    /**
337
     * Get/create instance of AbstractIndex associated with current table based on list of forming
338
     * column names.
339
     *
340
     * Example:
341
     * $table->index('key');
342
     * $table->index('key', 'key2');
343
     * $table->index(['key', 'key2']);
344
     *
345
     * @param mixed $columns Column name, or array of columns.
346
     *
347
     * @return AbstractIndex
348
     *
349
     * @throws SchemaException
350
     */
351
    public function index($columns): AbstractIndex
352
    {
353
        $columns = is_array($columns) ? $columns : func_get_args();
354
355
        foreach ($columns as $column) {
356
            if (!$this->hasColumn($column)) {
357
                throw new SchemaException("Undefined column '{$column}' in '{$this->getName()}'");
358
            }
359
        }
360
361
        if ($this->hasIndex($columns)) {
362
            return $this->currentState->findIndex($columns);
363
        }
364
365
        $index = $this->createIndex($this->createIdentifier('index', $columns));
366
        $index->columns($columns);
367
        $this->currentState->registerIndex($index);
368
369
        return $index;
370
    }
371
372
    /**
373
     * Get/create instance of AbstractReference associated with current table based on local column
374
     * name.
375
     *
376
     * @param string $column
377
     *
378
     * @return AbstractReference
379
     *
380
     * @throws SchemaException
381
     */
382
    public function foreign(string $column): AbstractReference
383
    {
384
        if (!$this->hasColumn($column)) {
385
            throw new SchemaException("Undefined column '{$column}' in '{$this->getName()}'");
386
        }
387
388
        if ($this->hasForeign($column)) {
389
            return $this->currentState->findForeign($column);
390
        }
391
392
        $foreign = $this->createReference($this->createIdentifier('foreign', [$column]));
393
        $foreign->column($column);
394
        $this->currentState->registerReference($foreign);
395
396
        //Let's ensure index existence
397
        $this->index($column);
398
399
        return $foreign;
400
    }
401
402
    /**
403
     * Rename column (only if column exists).
404
     *
405
     * @param string $column
406
     * @param string $name New column name.
407
     *
408
     * @return self
409
     *
410
     * @throws SchemaException
411
     */
412
    public function renameColumn(string $column, string $name): AbstractTable
413
    {
414
        if (!$this->hasColumn($column)) {
415
            throw new SchemaException("Undefined column '{$column}' in '{$this->getName()}'");
416
        }
417
418
        //Rename operation is simple about declaring new name
419
        $this->column($column)->setName($name);
420
421
        return $this;
422
    }
423
424
    /**
425
     * Rename index (only if index exists).
426
     *
427
     * @param array  $columns Index forming columns.
428
     * @param string $name    New index name.
429
     *
430
     * @return self
431
     *
432
     * @throws SchemaException
433
     */
434
    public function renameIndex(array $columns, string $name): AbstractTable
435
    {
436 View Code Duplication
        if (!$this->hasIndex($columns)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
437
            throw new SchemaException(
438
                "Undefined index ['" . join("', '", $columns) . "'] in '{$this->getName()}'"
439
            );
440
        }
441
442
        //Declaring new index name
443
        $this->index($columns)->setName($name);
444
445
        return $this;
446
    }
447
448
    /**
449
     * Drop column by it's name.
450
     *
451
     * @param string $column
452
     *
453
     * @return self
454
     *
455
     * @throws SchemaException
456
     */
457
    public function dropColumn(string $column): AbstractTable
458
    {
459
        if (!$this->hasColumn($column)) {
460
            throw new SchemaException("Undefined column '{$column}' in '{$this->getName()}'");
461
        }
462
463
        $state = $this->currentState;
464
465
        //Removing column first
466
        $column = $state->findColumn($column);
467
        $state->forgetColumn($column);
0 ignored issues
show
Bug introduced by
It seems like $column defined by $state->findColumn($column) on line 466 can be null; however, Spiral\Database\Schemas\TableState::forgetColumn() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
468
469
        if ($state->hasForeign($column)) {
470
            //Dropping related foreign key
471
            $state->forgetForeign($state->findForeign($column));
0 ignored issues
show
Documentation introduced by
$column is of type object<Spiral\Database\S...es\AbstractColumn>|null, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug introduced by
It seems like $state->findForeign($column) can be null; however, forgetForeign() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
472
        }
473
474
        //Dropping related indexes
475
        foreach ($state->getIndexes() as $index) {
476
            if (in_array($column->getName(), $index->getColumns())) {
477
                $state->forgetIndex($index);
478
            }
479
        }
480
481
        return $this;
482
    }
483
484
    /**
485
     * Drop index by it's forming columns.
486
     *
487
     * @param array $columns
488
     *
489
     * @return self
490
     *
491
     * @throws SchemaException
492
     */
493
    public function dropIndex(array $columns): AbstractTable
494
    {
495 View Code Duplication
        if (!$this->hasIndex($columns)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
496
            throw new SchemaException(
497
                "Undefined index ['" . join("', '", $columns) . "'] in '{$this->getName()}'"
498
            );
499
        }
500
501
        //Dropping index from current schema
502
        $this->currentState->forgetIndex($this->currentState->findIndex($columns));
0 ignored issues
show
Bug introduced by
It seems like $this->currentState->findIndex($columns) can be null; however, forgetIndex() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
503
504
        return $this;
505
    }
506
507
    /**
508
     * Drop foreign key by it's name.
509
     *
510
     * @param string $column
511
     *
512
     * @return self
513
     *
514
     * @throws SchemaException
515
     */
516
    public function dropForeign($column): AbstractTable
517
    {
518
        if (!$this->hasForeign($column)) {
519
            throw new SchemaException(
520
                "Undefined FK on '{$column}' in '{$this->getName()}'"
521
            );
522
        }
523
524
        //Dropping foreign from current schema
525
        $this->currentState->forgetForeign($this->currentState->findForeign($column));
0 ignored issues
show
Bug introduced by
It seems like $this->currentState->findForeign($column) can be null; however, forgetForeign() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
526
527
        return $this;
528
    }
529
530
    /**
531
     * Reset table state to new form.
532
     *
533
     * @param TableState $state Use null to flush table schema.
534
     *
535
     * @return self|$this
536
     */
537
    public function setState(TableState $state = null): AbstractTable
538
    {
539
        $this->currentState = new TableState($this->initialState->getName());
540
541
        if (!empty($state)) {
542
            $this->currentState->setName($state->getName());
543
            $this->currentState->syncState($state);
0 ignored issues
show
Documentation introduced by
$state is of type object<Spiral\Database\Schemas\TableState>, but the function expects a object<self>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
544
        }
545
546
        return $this;
547
    }
548
549
    /**
550
     * Reset table state to it initial form.
551
     *
552
     * @return self|$this
553
     */
554
    public function resetState(): AbstractTable
555
    {
556
        $this->setState($this->initialState);
557
558
        return $this;
559
    }
560
561
    /**
562
     * @return AbstractColumn|string
563
     */
564
    public function __toString(): string
565
    {
566
        return $this->getName();
567
    }
568
569
    /**
570
     * @return array
571
     */
572
    public function __debugInfo()
573
    {
574
        return [
575
            'name'        => $this->getName(),
576
            'primaryKeys' => $this->getPrimaryKeys(),
577
            'columns'     => array_values($this->getColumns()),
578
            'indexes'     => array_values($this->getIndexes()),
579
            'references'  => array_values($this->getForeigns()),
580
        ];
581
    }
582
583
    /**
584
     * Populate table schema with values from database.
585
     *
586
     * @param TableState $state
587
     */
588
    protected function initSchema(TableState $state)
589
    {
590
        foreach ($this->fetchColumns() as $column) {
591
            $state->registerColumn($column);
0 ignored issues
show
Compatibility introduced by
$column of type object<Spiral\Database\Schemas\ColumnInterface> is not a sub-type of object<Spiral\Database\S...totypes\AbstractColumn>. It seems like you assume a concrete implementation of the interface Spiral\Database\Schemas\ColumnInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
592
        }
593
594
        foreach ($this->fetchIndexes() as $index) {
595
            $state->registerIndex($index);
0 ignored issues
show
Compatibility introduced by
$index of type object<Spiral\Database\Schemas\IndexInterface> is not a sub-type of object<Spiral\Database\S...ototypes\AbstractIndex>. It seems like you assume a concrete implementation of the interface Spiral\Database\Schemas\IndexInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
596
        }
597
598
        foreach ($this->fetchReferences() as $foreign) {
599
            $state->registerReference($foreign);
0 ignored issues
show
Compatibility introduced by
$foreign of type object<Spiral\Database\S...mas\ReferenceInterface> is not a sub-type of object<Spiral\Database\S...ypes\AbstractReference>. It seems like you assume a concrete implementation of the interface Spiral\Database\Schemas\ReferenceInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
600
        }
601
602
        $state->setPrimaryKeys($this->fetchPrimaryKeys());
603
604
        //DBMS specific initialization can be placed here
605
    }
606
607
    /**
608
     * Fetch index declarations from database.
609
     *
610
     * @return ColumnInterface[]
611
     */
612
    abstract protected function fetchColumns(): array;
613
614
    /**
615
     * Fetch index declarations from database.
616
     *
617
     * @return IndexInterface[]
618
     */
619
    abstract protected function fetchIndexes(): array;
620
621
    /**
622
     * Fetch references declaration from database.
623
     *
624
     * @return ReferenceInterface[]
625
     */
626
    abstract protected function fetchReferences(): array;
627
628
    /**
629
     * Fetch names of primary keys from table.
630
     *
631
     * @return array
632
     */
633
    abstract protected function fetchPrimaryKeys(): array;
634
635
    /**
636
     * Create column with a given name.
637
     *
638
     * @param string $name
639
     *
640
     * @return AbstractColumn
641
     */
642
    abstract protected function createColumn(string $name): AbstractColumn;
643
644
    /**
645
     * Create index for a given set of columns.
646
     *
647
     * @param string $name
648
     *
649
     * @return AbstractIndex
650
     */
651
    abstract protected function createIndex(string $name): AbstractIndex;
652
653
    /**
654
     * Create reference on a given column set.
655
     *
656
     * @param string $name
657
     *
658
     * @return AbstractReference
659
     */
660
    abstract protected function createReference(string $name): AbstractReference;
661
662
    /**
663
     * Generate unique name for indexes and foreign keys.
664
     *
665
     * @param string $type
666
     * @param array  $columns
667
     *
668
     * @return string
669
     */
670
    protected function createIdentifier(string $type, array $columns): string
671
    {
672
        $name = $this->getName() . '_' . $type . '_' . join('_', $columns) . '_' . uniqid();
673
674
        if (strlen($name) > 64) {
675
            //Many DBMS has limitations on identifier length
676
            $name = md5($name);
677
        }
678
679
        return $name;
680
    }
681
682
    /**
683
     * @return ContainerInterface
684
     */
685
    protected function iocContainer()
686
    {
687
        //Falling back to driver specific container
688
        return $this->driver->iocContainer();
0 ignored issues
show
Bug introduced by
The method iocContainer() cannot be called from this context as it is declared protected in class Spiral\Core\Component.

This check looks for access to methods that are not accessible from the current context.

If you need to make a method accessible to another context you can raise its visibility level in the defining class.

Loading history...
689
    }
690
}