Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new feature to create all database models at once / Add database schema support #65

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
66 changes: 58 additions & 8 deletions src/Command/GenerateModelCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use Krlove\EloquentModelGenerator\Generator;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Illuminate\Support\Str;
use DB;

/**
* Class GenerateModelCommand
Expand Down Expand Up @@ -49,10 +51,55 @@ public function __construct(Generator $generator, AppConfig $appConfig)
public function fire()
{
$config = $this->createConfig();

$model = $this->generator->generateModel($config);

$this->output->writeln(sprintf('Model %s generated', $model->getName()->getName()));

if ($this->argument('class-name') === NULL) {
$tables = DB::connection()->getDoctrineSchemaManager()->listTables();
$defaultSchema = DB::connection()->getConfig()['schema'] ?? "";
foreach($tables as $table){
$currentSchema = $table->getNamespaceName();
$isManyToManyTable = FALSE;
if ($this->option('schema') === NULL ||
($this->option('schema') !== NULL && ($this->option('schema') === $currentSchema || ($currentSchema === NULL && $this->option('schema') === $defaultSchema)))
) {

//Check if the table is a many to many relationship (having its primary key composed of 2 foreign keys)
$primaryKey = $table->getPrimaryKey();
$foreignKeys = $table->getForeignKeys();

if ($primaryKey !== NULL && count($foreignKeys) === 2) {
$primaryKeyColumnNames = $table->getPrimaryKeyColumns();
$foreignKeysColumnNames = [];
foreach ($foreignKeys as $foreignKey) {
$foreignKeysColumnNames = array_merge($foreignKeysColumnNames,$foreignKey->getColumns());
}
if (count(array_intersect($foreignKeysColumnNames,$primaryKeyColumnNames)) === 2) {
$isManyToManyTable = TRUE;
}
}

if (!$isManyToManyTable) {
$tableName = $table->getShortestName($currentSchema);
$tableNameToSingular = Str::singular($tableName);



//Does not generate a model for many to many tables
if ($tableNameToSingular !== $tableName) {
$modelName = ucfirst(Str::camel(Str::singular($tableNameToSingular)));
$config->set('class_name',$modelName);
$config->set('table_name',$tableName);
$config->setSchemaName($table->getNamespaceName() ?? "");
$config->setDefaultSchemaName($defaultSchema);
$model = $this->generator->generateModel($config);
$this->output->writeln(sprintf('Model %s generated', $model->getName()->getName()));
}
}
}
}
} else {
$model = $this->generator->generateModel($config);
$this->output->writeln(sprintf('Model %s generated', $model->getName()->getName()));
}
}

/**
Expand Down Expand Up @@ -80,9 +127,9 @@ protected function createConfig()
}
$config[$option[0]] = $value;
}

$config['db_types'] = $this->appConfig->get('eloquent_model_generator.db_types');

return new Config($config, $this->appConfig->get('eloquent_model_generator.model_defaults'));
}

Expand All @@ -92,7 +139,7 @@ protected function createConfig()
protected function getArguments()
{
return [
['class-name', InputArgument::REQUIRED, 'Model class name'],
['class-name', InputArgument::OPTIONAL, 'Model class name'],
];
}

Expand All @@ -109,7 +156,10 @@ protected function getOptions()
['no-timestamps', 'ts', InputOption::VALUE_NONE, 'Set timestamps property to false', null],
['date-format', 'df', InputOption::VALUE_OPTIONAL, 'dateFormat property', null],
['connection', 'cn', InputOption::VALUE_OPTIONAL, 'Connection property', null],
['backup', 'b', InputOption::VALUE_NONE, 'Backup existing model', null]
['backup', 'b', InputOption::VALUE_NONE, 'Backup existing model', null],
['force-table-name', 'ftn', InputOption::VALUE_NONE, 'Force tableName property to be always set', null],
['schema', 's', InputOption::VALUE_OPTIONAL, 'Name of the database schema to generates models from, only used when class-name argument is not provided', null],
['no-class-phpdoc-block','ncpb', InputOption::VALUE_OPTIONAL, 'Does not generate the class php doc', null]
];
}
}
61 changes: 61 additions & 0 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ class Config
*/
protected $config;

/**
* @var string
*/
protected $defaultSchemaName;

/**
* @var string
*/
protected $schemaName;

/**
* Config constructor.
* @param array $inputConfig
Expand All @@ -29,6 +39,30 @@ public function __construct($inputConfig, $appConfig = null)
$this->config = $this->merge($inputConfig, $this->getBaseConfig());
}

public function getSchemaNameForQuery()
{
$schemaName = $this->getSchemaName();
//Cannot add the default schema name set in the connection for query
if ($schemaName === $this->defaultSchemaName) {
$schemaName = "";
}
if($schemaName !== ""){
$schemaName .= ".";
}
return $schemaName;
}

public function getSchemaName()
{
$schemaName = "";
if (isset($this->schemaName) && $this->schemaName !== "") {
$schemaName = $this->schemaName;
} elseif (isset($this->defaultSchemaName) && $this->defaultSchemaName !== "") {
$schemaName = $this->defaultSchemaName;
}
return $schemaName;
}

/**
* @param string $key
* @param mixed|null $default
Expand All @@ -39,6 +73,17 @@ public function get($key, $default = null)
return $this->has($key) ? $this->config[$key] : $default;
}

/**
* @param string $key
* @param mixed $value
*/
public function set($key, $value)
{
$this->config[$key] = $value;
}



/**
* @param string $key
* @return bool
Expand All @@ -48,6 +93,22 @@ public function has($key)
return isset($this->config[$key]);
}

/**
* @param string $schemaName
*/
public function setSchemaName(string $schemaName)
{
$this->schemaName = $schemaName;
}

/**
* @param string $defaultSchemaName
*/
public function setDefaultSchemaName(string $defaultSchemaName)
{
$this->defaultSchemaName = $defaultSchemaName;
}

/**
* @param array $high
* @param array $low
Expand Down
4 changes: 4 additions & 0 deletions src/EloquentModelBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ public function createModel(Config $config)
{
$model = new EloquentModel();

if($config->get('no_class_phpdoc_block') === false){
$model->setAddClassPhpDocBlock(FALSE);
}

$this->prepareProcessors();

foreach ($this->processors as $processor) {
Expand Down
16 changes: 16 additions & 0 deletions src/Model/EloquentModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class EloquentModel extends ClassModel
*/
protected $tableName;

protected $addClassPhpDocBlock = TRUE;

/**
* @param string $tableName
*
Expand All @@ -34,4 +36,18 @@ public function getTableName()
{
return $this->tableName;
}

public function setAddClassPhpDocBlock(bool $addClassPhpDocBlock){
$this->addClassPhpDocBlock = $addClassPhpDocBlock;
}

/**
* Convert virtual properties and methods to DocBlock content
*/
protected function prepareDocBlock()
{
if($this->addClassPhpDocBlock === FALSE){
parent::prepareDocBlock();
}
}
}
3 changes: 1 addition & 2 deletions src/Processor/CustomPrimaryKeyProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ public function process(EloquentModel $model, Config $config)
{
$schemaManager = $this->databaseManager->connection($config->get('connection'))->getDoctrineSchemaManager();
$prefix = $this->databaseManager->connection($config->get('connection'))->getTablePrefix();

$tableDetails = $schemaManager->listTableDetails($prefix . $model->getTableName());
$tableDetails = $schemaManager->listTableDetails($config->getSchemaNameForQuery() . $prefix . $model->getTableName());
$primaryKey = $tableDetails->getPrimaryKey();
if ($primaryKey === null) {
return;
Expand Down
4 changes: 2 additions & 2 deletions src/Processor/ExistenceCheckerProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public function process(EloquentModel $model, Config $config)
$schemaManager = $this->databaseManager->connection($config->get('connection'))->getDoctrineSchemaManager();
$prefix = $this->databaseManager->connection($config->get('connection'))->getTablePrefix();

if (!$schemaManager->tablesExist($prefix . $model->getTableName())) {
throw new GeneratorException(sprintf('Table %s does not exist', $prefix . $model->getTableName()));
if (!$schemaManager->tablesExist($config->getSchemaNameForQuery() . $prefix . $model->getTableName())) {
throw new GeneratorException(sprintf('Table %s does not exist', $config->getSchemaNameForQuery() . $prefix . $model->getTableName()));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Processor/FieldProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function process(EloquentModel $model, Config $config)
$schemaManager = $this->databaseManager->connection($config->get('connection'))->getDoctrineSchemaManager();
$prefix = $this->databaseManager->connection($config->get('connection'))->getTablePrefix();

$tableDetails = $schemaManager->listTableDetails($prefix . $model->getTableName());
$tableDetails = $schemaManager->listTableDetails($config->getSchemaNameForQuery() . $prefix . $model->getTableName());
$primaryColumnNames = $tableDetails->getPrimaryKey() ? $tableDetails->getPrimaryKey()->getColumns() : [];

$columnNames = [];
Expand Down
45 changes: 32 additions & 13 deletions src/Processor/RelationProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,16 @@ public function process(EloquentModel $model, Config $config)
$schemaManager = $this->databaseManager->connection($config->get('connection'))->getDoctrineSchemaManager();
$prefix = $this->databaseManager->connection($config->get('connection'))->getTablePrefix();

$foreignKeys = $schemaManager->listTableForeignKeys($prefix . $model->getTableName());
$foreignKeys = $schemaManager->listTableForeignKeys($config->getSchemaNameForQuery() . $prefix . $model->getTableName());
foreach ($foreignKeys as $tableForeignKey) {
$tableForeignColumns = $tableForeignKey->getForeignColumns();
if (count($tableForeignColumns) !== 1) {
continue;
}

$foreignTable = $schemaManager->listTableDetails($tableForeignKey->getForeignTableName());
$foreignTableTableNameWithoutSchema = $this->removePrefix($prefix, $foreignTable->getShortestName($foreignTable->getNamespaceName()));
$relation = new BelongsTo(
$this->removePrefix($prefix, $tableForeignKey->getForeignTableName()),
$this->removePrefix($prefix, $foreignTableTableNameWithoutSchema),
$tableForeignKey->getLocalColumns()[0],
$tableForeignColumns[0]
);
Expand All @@ -74,42 +75,60 @@ public function process(EloquentModel $model, Config $config)

$tables = $schemaManager->listTables();
foreach ($tables as $table) {
if ($table->getName() === $prefix . $model->getTableName()) {

if ($table->getName() === $config->getSchemaNameForQuery() . $prefix . $model->getTableName()) {
continue;
}

$foreignKeys = $table->getForeignKeys();
$primaryKeyColumnNames = [];
if ($table->getPrimaryKey()) {
$primaryKeyColumnNames = $table->getPrimaryKeyColumns();
}

$foreignKeysColumnNames = [];
if(count($foreignKeys) === 2){
foreach ($foreignKeys as $foreignKey) {
$foreignKeysColumnNames = array_merge($foreignKeysColumnNames,$foreignKey->getColumns());
}
}

foreach ($foreignKeys as $name => $foreignKey) {
if ($foreignKey->getForeignTableName() === $prefix . $model->getTableName()) {
if ($foreignKey->getForeignTableName() === $config->getSchemaNameForQuery() . $prefix . $model->getTableName()) {
$localColumns = $foreignKey->getLocalColumns();
if (count($localColumns) !== 1) {
continue;
}

if (count($foreignKeys) === 2 && count($table->getColumns()) === 2) {

if (count($foreignKeys) === 2 && count(array_intersect($foreignKeysColumnNames,$primaryKeyColumnNames)) === 2) {
$tableNameWithoutSchema = $table->getShortestName($table->getNamespaceName());

$keys = array_keys($foreignKeys);
$key = array_search($name, $keys) === 0 ? 1 : 0;
$secondForeignKey = $foreignKeys[$keys[$key]];
$secondForeignTable = $this->removePrefix($prefix, $secondForeignKey->getForeignTableName());
$secondForeignTable = $schemaManager->listTableDetails($secondForeignKey->getForeignTableName());
$secondForeignTableNameWithoutSchema = $this->removePrefix($prefix, $secondForeignTable->getShortestName($secondForeignTable->getNamespaceName()));

$relation = new BelongsToMany(
$secondForeignTable,
$this->removePrefix($prefix, $table->getName()),
$secondForeignTableNameWithoutSchema,
$this->removePrefix($prefix, $tableNameWithoutSchema),
$localColumns[0],
$secondForeignKey->getLocalColumns()[0]
);
$this->addRelation($model, $relation);

break;
} else {
$tableName = $this->removePrefix($prefix, $foreignKey->getLocalTableName());
$foreignTable = $foreignKey->getLocalTable();
$foreignTableNameWithoutSchema = $foreignTable->getShortestName($foreignTable->getNamespaceName());
$foreignTableNameWithoutSchema = $this->removePrefix($prefix, $foreignTableNameWithoutSchema);
$foreignColumn = $localColumns[0];
$localColumn = $foreignKey->getForeignColumns()[0];

if ($this->isColumnUnique($table, $foreignColumn)) {
$relation = new HasOne($tableName, $foreignColumn, $localColumn);
$relation = new HasOne($foreignTableNameWithoutSchema, $foreignColumn, $localColumn);
} else {
$relation = new HasMany($tableName, $foreignColumn, $localColumn);
$relation = new HasMany($foreignTableNameWithoutSchema, $foreignColumn, $localColumn);
}

$this->addRelation($model, $relation);
Expand Down
6 changes: 3 additions & 3 deletions src/Processor/TableNameProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ public function process(EloquentModel $model, Config $config)
$model->setName(new ClassNameModel($className, $this->helper->getShortClassName($baseClassName)));
$model->addUses(new UseClassModel(ltrim($baseClassName, '\\')));
$model->setTableName($tableName ?: $this->helper->getDefaultTableName($className));

if ($model->getTableName() !== $this->helper->getDefaultTableName($className)) {
$property = new PropertyModel('table', 'protected', $model->getTableName());
if ($model->getTableName() !== $this->helper->getDefaultTableName($className) || $config->get('force_table_name')) {
$property = new PropertyModel('table', 'protected', $config->getSchemaName().".".$model->getTableName());
$property->setDocBlock(new DocBlockModel('The table associated with the model.', '', '@var string'));
$model->addProperty($property);
}
Expand Down