/** * Migrate create schema * * @return \Doctrine\DBAL\Schema\Schema */ public function migrateCreateSchema() { $entityName = $this->mapper->entity(); $table = $entityName::table(); $fields = $this->mapper->entityManager()->fields(); $fieldIndexes = $this->mapper->entityManager()->fieldKeys(); $schema = new \Doctrine\DBAL\Schema\Schema(); $table = $schema->createTable($table); foreach ($fields as $field => $fieldInfo) { $fieldType = $fieldInfo['type']; unset($fieldInfo['type']); $table->addColumn($field, $fieldType, $fieldInfo); } // PRIMARY if ($fieldIndexes['primary']) { $table->setPrimaryKey($fieldIndexes['primary']); } // UNIQUE foreach ($fieldIndexes['unique'] as $keyName => $keyFields) { $table->addUniqueIndex($keyFields, $keyName); } // INDEX foreach ($fieldIndexes['index'] as $keyName => $keyFields) { $table->addIndex($keyFields, $keyName); } return $schema; }
/** * Taken given field name/value inputs and map them to their aliased names */ public function dataWithFieldAliasMappings(array $data) { $fields = $this->mapper->entityManager()->fields(); $fieldMappings = []; foreach ($data as $field => $value) { $fieldAlias = $this->escapeIdentifier(isset($fields[$field]) ? $fields[$field]['column'] : $field); $fieldMappings[$fieldAlias] = $value; } return $fieldMappings; }
/** * Get field name with table alias appended * @param string $field * @param bool $escaped * @return string */ public function fieldWithAlias($field, $escaped = true) { $fieldInfo = $this->_mapper->entityManager()->fields(); // Determine real field name (column alias support) if (isset($fieldInfo[$field])) { $field = $fieldInfo[$field]['column']; } $field = $this->_tableName . '.' . $field; return $escaped ? $this->escapeIdentifier($field) : $field; }
/** * Add foreign keys from BelongsTo relations to the table schema * @param Table $table * @return Table */ protected function addForeignKeys(Table $table) { $entityName = $this->mapper->entity(); $entity = new $entityName(); $relations = $entityName::relations($this->mapper, $entity); $fields = $this->mapper->entityManager()->fields(); foreach ($relations as $relationName => $relation) { if ($relation instanceof BelongsTo) { $fieldInfo = $fields[$relation->localKey()]; if ($fieldInfo['foreignkey'] === false) { continue; } $foreignTableMapper = $relation->mapper()->getMapper($relation->entityName()); $foreignTable = $foreignTableMapper->table(); $foreignSchemaManager = $foreignTableMapper->connection()->getSchemaManager(); $foreignTableObject = $foreignSchemaManager->listTableDetails($foreignTable); $foreignTableColumns = $foreignTableObject->getColumns(); $foreignTableNotExists = empty($foreignTableColumns); $foreignKeyNotExists = !array_key_exists($relation->foreignKey(), $foreignTableColumns); // We need to use the is_a() function because the there is some inconsistency in entity names (leading slash) $notRecursiveForeignKey = !is_a($entity, $relation->entityName()); /* Migrate foreign table if: * - the foreign table not exists * - the foreign key not exists * - the foreign table is not the same as the current table (recursion check) * This migration eliminates the 'Integrity constraint violation' error */ if (($foreignTableNotExists || $foreignKeyNotExists) && $notRecursiveForeignKey) { $foreignTableMapper->migrate(); } $onUpdate = !is_null($fieldInfo['onUpdate']) ? $fieldInfo['onUpdate'] : "CASCADE"; if (!is_null($fieldInfo['onDelete'])) { $onDelete = $fieldInfo['onDelete']; } else { if ($fieldInfo['notnull']) { $onDelete = "CASCADE"; } else { $onDelete = "SET NULL"; } } // Field alias support $fieldAliasMappings = $this->mapper->entityManager()->fieldAliasMappings(); if (isset($fieldAliasMappings[$relation->localKey()])) { $localKey = $fieldAliasMappings[$relation->localKey()]; } else { $localKey = $relation->localKey(); } $fkName = $this->mapper->table() . '_fk_' . $relationName; $table->addForeignKeyConstraint($foreignTable, [$localKey], [$relation->foreignKey()], ["onDelete" => $onDelete, "onUpdate" => $onUpdate], $fkName); } } return $table; }
/** * Migrate create schema * * @return \Doctrine\DBAL\Schema\Schema */ public function migrateCreateSchema() { $entityName = $this->mapper->entity(); $table = $entityName::table(); $fields = $this->mapper->entityManager()->fields(); $fieldIndexes = $this->mapper->entityManager()->fieldKeys(); $schema = new \Doctrine\DBAL\Schema\Schema(); $table = $schema->createTable($table); foreach ($fields as $field => $fieldInfo) { $fieldType = $fieldInfo['type']; unset($fieldInfo['type']); $table->addColumn($field, $fieldType, $fieldInfo); } // PRIMARY if ($fieldIndexes['primary']) { $table->setPrimaryKey($fieldIndexes['primary']); } // UNIQUE foreach ($fieldIndexes['unique'] as $keyName => $keyFields) { $table->addUniqueIndex($keyFields, $keyName); } // INDEX foreach ($fieldIndexes['index'] as $keyName => $keyFields) { $table->addIndex($keyFields, $keyName); } // Add foreign key constraints if necessary. $relations = call_user_func(array($entityName, 'relations'), $this->mapper, new $entityName()); // Skip, if there are no relations added. if (count($relations)) { foreach ($relations as $name => $relation) { /** * Since OneToMany and ManyToMany are at the inverse side * of the relations, their purpose is to return a collection * of entities/objects and there are no foreign keys on this side. * * So, we skip those entities, and expect a ManyToOne relation to be * defined on the owning side. */ if ($relation instanceof Relation\HasMany || $relation instanceof Relation\HasManyThrough) { continue; } $parentEntity = $relation->entityName(); $foreignTable = call_user_func([$parentEntity, 'table']); $localKey = $relation->localKey(); $foreignKey = $relation->foreignKey(); /** * Create an empty array that would hold our constraint options. * By default we can create a foreign key without having to * passing onDelete/onUpdate clauses, so at the very least, * an empty array is required. * * This array structure should be pairs of "column" => "option" * <code> * array("onDelete" => "CASCADE", "onUpdate" => "CASCADE") * </code> */ $constrains = []; /** * Check if onUpdate clause is been added. * If there is, add it to $constraints array. */ if (isset($fieldIndexes['constraints']['onUpdate'])) { if (array_key_exists($localKey, $fieldIndexes['constraints']['onUpdate'])) { $constrains['onUpdate'] = $fieldIndexes['constraints']['onUpdate'][$localKey]; } } /** * Check if onDelete clause is been added. * If there is, add it to $constraints array. */ if (isset($fieldIndexes['constraints']['onDelete'])) { if (array_key_exists($localKey, $fieldIndexes['constraints']['onDelete'])) { $constrains['onDelete'] = $fieldIndexes['constraints']['onDelete'][$localKey]; } } // Create the foreign key. $table->addForeignKeyConstraint($foreignTable, [$localKey], [$foreignKey], $constrains); } } return $schema; }