diff options
Diffstat (limited to 'vendor/doctrine/orm/src/Mapping/Driver/DatabaseDriver.php')
| -rw-r--r-- | vendor/doctrine/orm/src/Mapping/Driver/DatabaseDriver.php | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/vendor/doctrine/orm/src/Mapping/Driver/DatabaseDriver.php b/vendor/doctrine/orm/src/Mapping/Driver/DatabaseDriver.php new file mode 100644 index 0000000..49e2e93 --- /dev/null +++ b/vendor/doctrine/orm/src/Mapping/Driver/DatabaseDriver.php | |||
| @@ -0,0 +1,528 @@ | |||
| 1 | <?php | ||
| 2 | |||
| 3 | declare(strict_types=1); | ||
| 4 | |||
| 5 | namespace Doctrine\ORM\Mapping\Driver; | ||
| 6 | |||
| 7 | use Doctrine\DBAL\Schema\AbstractSchemaManager; | ||
| 8 | use Doctrine\DBAL\Schema\Column; | ||
| 9 | use Doctrine\DBAL\Schema\SchemaException; | ||
| 10 | use Doctrine\DBAL\Schema\Table; | ||
| 11 | use Doctrine\DBAL\Types\Type; | ||
| 12 | use Doctrine\DBAL\Types\Types; | ||
| 13 | use Doctrine\Inflector\Inflector; | ||
| 14 | use Doctrine\Inflector\InflectorFactory; | ||
| 15 | use Doctrine\ORM\Mapping\ClassMetadata; | ||
| 16 | use Doctrine\ORM\Mapping\MappingException; | ||
| 17 | use Doctrine\Persistence\Mapping\ClassMetadata as PersistenceClassMetadata; | ||
| 18 | use Doctrine\Persistence\Mapping\Driver\MappingDriver; | ||
| 19 | use InvalidArgumentException; | ||
| 20 | use TypeError; | ||
| 21 | |||
| 22 | use function array_diff; | ||
| 23 | use function array_keys; | ||
| 24 | use function array_merge; | ||
| 25 | use function assert; | ||
| 26 | use function count; | ||
| 27 | use function current; | ||
| 28 | use function get_debug_type; | ||
| 29 | use function in_array; | ||
| 30 | use function preg_replace; | ||
| 31 | use function sort; | ||
| 32 | use function sprintf; | ||
| 33 | use function strtolower; | ||
| 34 | |||
| 35 | /** | ||
| 36 | * The DatabaseDriver reverse engineers the mapping metadata from a database. | ||
| 37 | * | ||
| 38 | * @link www.doctrine-project.org | ||
| 39 | */ | ||
| 40 | class DatabaseDriver implements MappingDriver | ||
| 41 | { | ||
| 42 | /** | ||
| 43 | * Replacement for {@see Types::ARRAY}. | ||
| 44 | * | ||
| 45 | * To be removed as soon as support for DBAL 3 is dropped. | ||
| 46 | */ | ||
| 47 | private const ARRAY = 'array'; | ||
| 48 | |||
| 49 | /** | ||
| 50 | * Replacement for {@see Types::OBJECT}. | ||
| 51 | * | ||
| 52 | * To be removed as soon as support for DBAL 3 is dropped. | ||
| 53 | */ | ||
| 54 | private const OBJECT = 'object'; | ||
| 55 | |||
| 56 | /** @var array<string,Table>|null */ | ||
| 57 | private array|null $tables = null; | ||
| 58 | |||
| 59 | /** @var array<class-string, string> */ | ||
| 60 | private array $classToTableNames = []; | ||
| 61 | |||
| 62 | /** @psalm-var array<string, Table> */ | ||
| 63 | private array $manyToManyTables = []; | ||
| 64 | |||
| 65 | /** @var mixed[] */ | ||
| 66 | private array $classNamesForTables = []; | ||
| 67 | |||
| 68 | /** @var mixed[] */ | ||
| 69 | private array $fieldNamesForColumns = []; | ||
| 70 | |||
| 71 | /** | ||
| 72 | * The namespace for the generated entities. | ||
| 73 | */ | ||
| 74 | private string|null $namespace = null; | ||
| 75 | |||
| 76 | private Inflector $inflector; | ||
| 77 | |||
| 78 | public function __construct(private readonly AbstractSchemaManager $sm) | ||
| 79 | { | ||
| 80 | $this->inflector = InflectorFactory::create()->build(); | ||
| 81 | } | ||
| 82 | |||
| 83 | /** | ||
| 84 | * Set the namespace for the generated entities. | ||
| 85 | */ | ||
| 86 | public function setNamespace(string $namespace): void | ||
| 87 | { | ||
| 88 | $this->namespace = $namespace; | ||
| 89 | } | ||
| 90 | |||
| 91 | public function isTransient(string $className): bool | ||
| 92 | { | ||
| 93 | return true; | ||
| 94 | } | ||
| 95 | |||
| 96 | /** | ||
| 97 | * {@inheritDoc} | ||
| 98 | */ | ||
| 99 | public function getAllClassNames(): array | ||
| 100 | { | ||
| 101 | $this->reverseEngineerMappingFromDatabase(); | ||
| 102 | |||
| 103 | return array_keys($this->classToTableNames); | ||
| 104 | } | ||
| 105 | |||
| 106 | /** | ||
| 107 | * Sets class name for a table. | ||
| 108 | */ | ||
| 109 | public function setClassNameForTable(string $tableName, string $className): void | ||
| 110 | { | ||
| 111 | $this->classNamesForTables[$tableName] = $className; | ||
| 112 | } | ||
| 113 | |||
| 114 | /** | ||
| 115 | * Sets field name for a column on a specific table. | ||
| 116 | */ | ||
| 117 | public function setFieldNameForColumn(string $tableName, string $columnName, string $fieldName): void | ||
| 118 | { | ||
| 119 | $this->fieldNamesForColumns[$tableName][$columnName] = $fieldName; | ||
| 120 | } | ||
| 121 | |||
| 122 | /** | ||
| 123 | * Sets tables manually instead of relying on the reverse engineering capabilities of SchemaManager. | ||
| 124 | * | ||
| 125 | * @param Table[] $entityTables | ||
| 126 | * @param Table[] $manyToManyTables | ||
| 127 | * @psalm-param list<Table> $entityTables | ||
| 128 | * @psalm-param list<Table> $manyToManyTables | ||
| 129 | */ | ||
| 130 | public function setTables(array $entityTables, array $manyToManyTables): void | ||
| 131 | { | ||
| 132 | $this->tables = $this->manyToManyTables = $this->classToTableNames = []; | ||
| 133 | |||
| 134 | foreach ($entityTables as $table) { | ||
| 135 | $className = $this->getClassNameForTable($table->getName()); | ||
| 136 | |||
| 137 | $this->classToTableNames[$className] = $table->getName(); | ||
| 138 | $this->tables[$table->getName()] = $table; | ||
| 139 | } | ||
| 140 | |||
| 141 | foreach ($manyToManyTables as $table) { | ||
| 142 | $this->manyToManyTables[$table->getName()] = $table; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | public function setInflector(Inflector $inflector): void | ||
| 147 | { | ||
| 148 | $this->inflector = $inflector; | ||
| 149 | } | ||
| 150 | |||
| 151 | /** | ||
| 152 | * {@inheritDoc} | ||
| 153 | * | ||
| 154 | * @psalm-param class-string<T> $className | ||
| 155 | * @psalm-param ClassMetadata<T> $metadata | ||
| 156 | * | ||
| 157 | * @template T of object | ||
| 158 | */ | ||
| 159 | public function loadMetadataForClass(string $className, PersistenceClassMetadata $metadata): void | ||
| 160 | { | ||
| 161 | if (! $metadata instanceof ClassMetadata) { | ||
| 162 | throw new TypeError(sprintf( | ||
| 163 | 'Argument #2 passed to %s() must be an instance of %s, %s given.', | ||
| 164 | __METHOD__, | ||
| 165 | ClassMetadata::class, | ||
| 166 | get_debug_type($metadata), | ||
| 167 | )); | ||
| 168 | } | ||
| 169 | |||
| 170 | $this->reverseEngineerMappingFromDatabase(); | ||
| 171 | |||
| 172 | if (! isset($this->classToTableNames[$className])) { | ||
| 173 | throw new InvalidArgumentException('Unknown class ' . $className); | ||
| 174 | } | ||
| 175 | |||
| 176 | $tableName = $this->classToTableNames[$className]; | ||
| 177 | |||
| 178 | $metadata->name = $className; | ||
| 179 | $metadata->table['name'] = $tableName; | ||
| 180 | |||
| 181 | $this->buildIndexes($metadata); | ||
| 182 | $this->buildFieldMappings($metadata); | ||
| 183 | $this->buildToOneAssociationMappings($metadata); | ||
| 184 | |||
| 185 | foreach ($this->manyToManyTables as $manyTable) { | ||
| 186 | foreach ($manyTable->getForeignKeys() as $foreignKey) { | ||
| 187 | // foreign key maps to the table of the current entity, many to many association probably exists | ||
| 188 | if (! (strtolower($tableName) === strtolower($foreignKey->getForeignTableName()))) { | ||
| 189 | continue; | ||
| 190 | } | ||
| 191 | |||
| 192 | $myFk = $foreignKey; | ||
| 193 | $otherFk = null; | ||
| 194 | |||
| 195 | foreach ($manyTable->getForeignKeys() as $foreignKey) { | ||
| 196 | if ($foreignKey !== $myFk) { | ||
| 197 | $otherFk = $foreignKey; | ||
| 198 | break; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | if (! $otherFk) { | ||
| 203 | // the definition of this many to many table does not contain | ||
| 204 | // enough foreign key information to continue reverse engineering. | ||
| 205 | continue; | ||
| 206 | } | ||
| 207 | |||
| 208 | $localColumn = current($myFk->getLocalColumns()); | ||
| 209 | |||
| 210 | $associationMapping = []; | ||
| 211 | $associationMapping['fieldName'] = $this->getFieldNameForColumn($manyTable->getName(), current($otherFk->getLocalColumns()), true); | ||
| 212 | $associationMapping['targetEntity'] = $this->getClassNameForTable($otherFk->getForeignTableName()); | ||
| 213 | |||
| 214 | if (current($manyTable->getColumns())->getName() === $localColumn) { | ||
| 215 | $associationMapping['inversedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getLocalColumns()), true); | ||
| 216 | $associationMapping['joinTable'] = [ | ||
| 217 | 'name' => strtolower($manyTable->getName()), | ||
| 218 | 'joinColumns' => [], | ||
| 219 | 'inverseJoinColumns' => [], | ||
| 220 | ]; | ||
| 221 | |||
| 222 | $fkCols = $myFk->getForeignColumns(); | ||
| 223 | $cols = $myFk->getLocalColumns(); | ||
| 224 | |||
| 225 | for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) { | ||
| 226 | $associationMapping['joinTable']['joinColumns'][] = [ | ||
| 227 | 'name' => $cols[$i], | ||
| 228 | 'referencedColumnName' => $fkCols[$i], | ||
| 229 | ]; | ||
| 230 | } | ||
| 231 | |||
| 232 | $fkCols = $otherFk->getForeignColumns(); | ||
| 233 | $cols = $otherFk->getLocalColumns(); | ||
| 234 | |||
| 235 | for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) { | ||
| 236 | $associationMapping['joinTable']['inverseJoinColumns'][] = [ | ||
| 237 | 'name' => $cols[$i], | ||
| 238 | 'referencedColumnName' => $fkCols[$i], | ||
| 239 | ]; | ||
| 240 | } | ||
| 241 | } else { | ||
| 242 | $associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getLocalColumns()), true); | ||
| 243 | } | ||
| 244 | |||
| 245 | $metadata->mapManyToMany($associationMapping); | ||
| 246 | |||
| 247 | break; | ||
| 248 | } | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | /** @throws MappingException */ | ||
| 253 | private function reverseEngineerMappingFromDatabase(): void | ||
| 254 | { | ||
| 255 | if ($this->tables !== null) { | ||
| 256 | return; | ||
| 257 | } | ||
| 258 | |||
| 259 | $this->tables = $this->manyToManyTables = $this->classToTableNames = []; | ||
| 260 | |||
| 261 | foreach ($this->sm->listTables() as $table) { | ||
| 262 | $tableName = $table->getName(); | ||
| 263 | $foreignKeys = $table->getForeignKeys(); | ||
| 264 | |||
| 265 | $allForeignKeyColumns = []; | ||
| 266 | |||
| 267 | foreach ($foreignKeys as $foreignKey) { | ||
| 268 | $allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns()); | ||
| 269 | } | ||
| 270 | |||
| 271 | $primaryKey = $table->getPrimaryKey(); | ||
| 272 | if ($primaryKey === null) { | ||
| 273 | throw new MappingException( | ||
| 274 | 'Table ' . $tableName . ' has no primary key. Doctrine does not ' . | ||
| 275 | "support reverse engineering from tables that don't have a primary key.", | ||
| 276 | ); | ||
| 277 | } | ||
| 278 | |||
| 279 | $pkColumns = $primaryKey->getColumns(); | ||
| 280 | |||
| 281 | sort($pkColumns); | ||
| 282 | sort($allForeignKeyColumns); | ||
| 283 | |||
| 284 | if ($pkColumns === $allForeignKeyColumns && count($foreignKeys) === 2) { | ||
| 285 | $this->manyToManyTables[$tableName] = $table; | ||
| 286 | } else { | ||
| 287 | // lower-casing is necessary because of Oracle Uppercase Tablenames, | ||
| 288 | // assumption is lower-case + underscore separated. | ||
| 289 | $className = $this->getClassNameForTable($tableName); | ||
| 290 | |||
| 291 | $this->tables[$tableName] = $table; | ||
| 292 | $this->classToTableNames[$className] = $tableName; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | /** | ||
| 298 | * Build indexes from a class metadata. | ||
| 299 | */ | ||
| 300 | private function buildIndexes(ClassMetadata $metadata): void | ||
| 301 | { | ||
| 302 | $tableName = $metadata->table['name']; | ||
| 303 | $indexes = $this->tables[$tableName]->getIndexes(); | ||
| 304 | |||
| 305 | foreach ($indexes as $index) { | ||
| 306 | if ($index->isPrimary()) { | ||
| 307 | continue; | ||
| 308 | } | ||
| 309 | |||
| 310 | $indexName = $index->getName(); | ||
| 311 | $indexColumns = $index->getColumns(); | ||
| 312 | $constraintType = $index->isUnique() | ||
| 313 | ? 'uniqueConstraints' | ||
| 314 | : 'indexes'; | ||
| 315 | |||
| 316 | $metadata->table[$constraintType][$indexName]['columns'] = $indexColumns; | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | /** | ||
| 321 | * Build field mapping from class metadata. | ||
| 322 | */ | ||
| 323 | private function buildFieldMappings(ClassMetadata $metadata): void | ||
| 324 | { | ||
| 325 | $tableName = $metadata->table['name']; | ||
| 326 | $columns = $this->tables[$tableName]->getColumns(); | ||
| 327 | $primaryKeys = $this->getTablePrimaryKeys($this->tables[$tableName]); | ||
| 328 | $foreignKeys = $this->tables[$tableName]->getForeignKeys(); | ||
| 329 | $allForeignKeys = []; | ||
| 330 | |||
| 331 | foreach ($foreignKeys as $foreignKey) { | ||
| 332 | $allForeignKeys = array_merge($allForeignKeys, $foreignKey->getLocalColumns()); | ||
| 333 | } | ||
| 334 | |||
| 335 | $ids = []; | ||
| 336 | $fieldMappings = []; | ||
| 337 | |||
| 338 | foreach ($columns as $column) { | ||
| 339 | if (in_array($column->getName(), $allForeignKeys, true)) { | ||
| 340 | continue; | ||
| 341 | } | ||
| 342 | |||
| 343 | $fieldMapping = $this->buildFieldMapping($tableName, $column); | ||
| 344 | |||
| 345 | if ($primaryKeys && in_array($column->getName(), $primaryKeys, true)) { | ||
| 346 | $fieldMapping['id'] = true; | ||
| 347 | $ids[] = $fieldMapping; | ||
| 348 | } | ||
| 349 | |||
| 350 | $fieldMappings[] = $fieldMapping; | ||
| 351 | } | ||
| 352 | |||
| 353 | // We need to check for the columns here, because we might have associations as id as well. | ||
| 354 | if ($ids && count($primaryKeys) === 1) { | ||
| 355 | $metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_AUTO); | ||
| 356 | } | ||
| 357 | |||
| 358 | foreach ($fieldMappings as $fieldMapping) { | ||
| 359 | $metadata->mapField($fieldMapping); | ||
| 360 | } | ||
| 361 | } | ||
| 362 | |||
| 363 | /** | ||
| 364 | * Build field mapping from a schema column definition | ||
| 365 | * | ||
| 366 | * @return mixed[] | ||
| 367 | * @psalm-return array{ | ||
| 368 | * fieldName: string, | ||
| 369 | * columnName: string, | ||
| 370 | * type: string, | ||
| 371 | * nullable: bool, | ||
| 372 | * options: array{ | ||
| 373 | * unsigned?: bool, | ||
| 374 | * fixed?: bool, | ||
| 375 | * comment: string|null, | ||
| 376 | * default?: mixed | ||
| 377 | * }, | ||
| 378 | * precision?: int, | ||
| 379 | * scale?: int, | ||
| 380 | * length?: int|null | ||
| 381 | * } | ||
| 382 | */ | ||
| 383 | private function buildFieldMapping(string $tableName, Column $column): array | ||
| 384 | { | ||
| 385 | $fieldMapping = [ | ||
| 386 | 'fieldName' => $this->getFieldNameForColumn($tableName, $column->getName(), false), | ||
| 387 | 'columnName' => $column->getName(), | ||
| 388 | 'type' => Type::getTypeRegistry()->lookupName($column->getType()), | ||
| 389 | 'nullable' => ! $column->getNotnull(), | ||
| 390 | 'options' => [ | ||
| 391 | 'comment' => $column->getComment(), | ||
| 392 | ], | ||
| 393 | ]; | ||
| 394 | |||
| 395 | // Type specific elements | ||
| 396 | switch ($fieldMapping['type']) { | ||
| 397 | case self::ARRAY: | ||
| 398 | case Types::BLOB: | ||
| 399 | case Types::GUID: | ||
| 400 | case self::OBJECT: | ||
| 401 | case Types::SIMPLE_ARRAY: | ||
| 402 | case Types::STRING: | ||
| 403 | case Types::TEXT: | ||
| 404 | $fieldMapping['length'] = $column->getLength(); | ||
| 405 | $fieldMapping['options']['fixed'] = $column->getFixed(); | ||
| 406 | break; | ||
| 407 | |||
| 408 | case Types::DECIMAL: | ||
| 409 | case Types::FLOAT: | ||
| 410 | $fieldMapping['precision'] = $column->getPrecision(); | ||
| 411 | $fieldMapping['scale'] = $column->getScale(); | ||
| 412 | break; | ||
| 413 | |||
| 414 | case Types::INTEGER: | ||
| 415 | case Types::BIGINT: | ||
| 416 | case Types::SMALLINT: | ||
| 417 | $fieldMapping['options']['unsigned'] = $column->getUnsigned(); | ||
| 418 | break; | ||
| 419 | } | ||
| 420 | |||
| 421 | // Default | ||
| 422 | $default = $column->getDefault(); | ||
| 423 | if ($default !== null) { | ||
| 424 | $fieldMapping['options']['default'] = $default; | ||
| 425 | } | ||
| 426 | |||
| 427 | return $fieldMapping; | ||
| 428 | } | ||
| 429 | |||
| 430 | /** | ||
| 431 | * Build to one (one to one, many to one) association mapping from class metadata. | ||
| 432 | */ | ||
| 433 | private function buildToOneAssociationMappings(ClassMetadata $metadata): void | ||
| 434 | { | ||
| 435 | assert($this->tables !== null); | ||
| 436 | |||
| 437 | $tableName = $metadata->table['name']; | ||
| 438 | $primaryKeys = $this->getTablePrimaryKeys($this->tables[$tableName]); | ||
| 439 | $foreignKeys = $this->tables[$tableName]->getForeignKeys(); | ||
| 440 | |||
| 441 | foreach ($foreignKeys as $foreignKey) { | ||
| 442 | $foreignTableName = $foreignKey->getForeignTableName(); | ||
| 443 | $fkColumns = $foreignKey->getLocalColumns(); | ||
| 444 | $fkForeignColumns = $foreignKey->getForeignColumns(); | ||
| 445 | $localColumn = current($fkColumns); | ||
| 446 | $associationMapping = [ | ||
| 447 | 'fieldName' => $this->getFieldNameForColumn($tableName, $localColumn, true), | ||
| 448 | 'targetEntity' => $this->getClassNameForTable($foreignTableName), | ||
| 449 | ]; | ||
| 450 | |||
| 451 | if (isset($metadata->fieldMappings[$associationMapping['fieldName']])) { | ||
| 452 | $associationMapping['fieldName'] .= '2'; // "foo" => "foo2" | ||
| 453 | } | ||
| 454 | |||
| 455 | if ($primaryKeys && in_array($localColumn, $primaryKeys, true)) { | ||
| 456 | $associationMapping['id'] = true; | ||
| 457 | } | ||
| 458 | |||
| 459 | for ($i = 0, $fkColumnsCount = count($fkColumns); $i < $fkColumnsCount; $i++) { | ||
| 460 | $associationMapping['joinColumns'][] = [ | ||
| 461 | 'name' => $fkColumns[$i], | ||
| 462 | 'referencedColumnName' => $fkForeignColumns[$i], | ||
| 463 | ]; | ||
| 464 | } | ||
| 465 | |||
| 466 | // Here we need to check if $fkColumns are the same as $primaryKeys | ||
| 467 | if (! array_diff($fkColumns, $primaryKeys)) { | ||
| 468 | $metadata->mapOneToOne($associationMapping); | ||
| 469 | } else { | ||
| 470 | $metadata->mapManyToOne($associationMapping); | ||
| 471 | } | ||
| 472 | } | ||
| 473 | } | ||
| 474 | |||
| 475 | /** | ||
| 476 | * Retrieve schema table definition primary keys. | ||
| 477 | * | ||
| 478 | * @return string[] | ||
| 479 | */ | ||
| 480 | private function getTablePrimaryKeys(Table $table): array | ||
| 481 | { | ||
| 482 | try { | ||
| 483 | return $table->getPrimaryKey()->getColumns(); | ||
| 484 | } catch (SchemaException) { | ||
| 485 | // Do nothing | ||
| 486 | } | ||
| 487 | |||
| 488 | return []; | ||
| 489 | } | ||
| 490 | |||
| 491 | /** | ||
| 492 | * Returns the mapped class name for a table if it exists. Otherwise return "classified" version. | ||
| 493 | * | ||
| 494 | * @psalm-return class-string | ||
| 495 | */ | ||
| 496 | private function getClassNameForTable(string $tableName): string | ||
| 497 | { | ||
| 498 | if (isset($this->classNamesForTables[$tableName])) { | ||
| 499 | return $this->namespace . $this->classNamesForTables[$tableName]; | ||
| 500 | } | ||
| 501 | |||
| 502 | return $this->namespace . $this->inflector->classify(strtolower($tableName)); | ||
| 503 | } | ||
| 504 | |||
| 505 | /** | ||
| 506 | * Return the mapped field name for a column, if it exists. Otherwise return camelized version. | ||
| 507 | * | ||
| 508 | * @param bool $fk Whether the column is a foreignkey or not. | ||
| 509 | */ | ||
| 510 | private function getFieldNameForColumn( | ||
| 511 | string $tableName, | ||
| 512 | string $columnName, | ||
| 513 | bool $fk = false, | ||
| 514 | ): string { | ||
| 515 | if (isset($this->fieldNamesForColumns[$tableName], $this->fieldNamesForColumns[$tableName][$columnName])) { | ||
| 516 | return $this->fieldNamesForColumns[$tableName][$columnName]; | ||
| 517 | } | ||
| 518 | |||
| 519 | $columnName = strtolower($columnName); | ||
| 520 | |||
| 521 | // Replace _id if it is a foreignkey column | ||
| 522 | if ($fk) { | ||
| 523 | $columnName = preg_replace('/_id$/', '', $columnName); | ||
| 524 | } | ||
| 525 | |||
| 526 | return $this->inflector->camelize($columnName); | ||
| 527 | } | ||
| 528 | } | ||
