Skip to content

Commit 832d266

Browse files
authored
Fix #489: Added support for the ::class constant in model generator via the useClassConstant setting
1 parent 4f24ccc commit 832d266

File tree

5 files changed

+160
-31
lines changed

5 files changed

+160
-31
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Yii Framework 2 gii extension Change Log
44
2.2.5 under development
55
-----------------------
66

7-
- no changes in this release.
7+
- Ehn #489: Added support for the `::class` constant in model generator via the `useClassConstant` setting (rhertogh)
88

99

1010
2.2.4 December 30, 2021

src/generators/model/Generator.php

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class Generator extends \yii\gii\Generator
5050
public $baseClass = 'yii\db\ActiveRecord';
5151
public $generateRelations = self::RELATIONS_ALL;
5252
public $generateJunctionRelationMode = self::JUNCTION_RELATION_VIA_TABLE;
53+
public $useClassConstant = null;
5354
public $generateRelationsFromCurrentSchema = true;
5455
public $generateLabelsFromComments = false;
5556
public $useTablePrefix = false;
@@ -76,6 +77,14 @@ class Generator extends \yii\gii\Generator
7677
*/
7778
protected $classNames = [];
7879

80+
public function init()
81+
{
82+
parent::init();
83+
84+
if ($this->useClassConstant === null) {
85+
$this->useClassConstant = PHP_VERSION_ID >= 50500;
86+
}
87+
}
7988

8089
/**
8190
* @inheritdoc
@@ -120,7 +129,7 @@ public function rules()
120129
[['generateRelations'], 'in', 'range' => [self::RELATIONS_NONE, self::RELATIONS_ALL, self::RELATIONS_ALL_INVERSE]],
121130
[['generateJunctionRelationMode'], 'in', 'range' => [self::JUNCTION_RELATION_VIA_TABLE, self::JUNCTION_RELATION_VIA_MODEL]],
122131
[
123-
['generateLabelsFromComments', 'useTablePrefix', 'useSchemaName', 'generateQuery', 'generateRelationsFromCurrentSchema', 'enableI18N', 'standardizeCapitals', 'singularize'],
132+
['generateLabelsFromComments', 'useTablePrefix', 'useSchemaName', 'generateQuery', 'generateRelationsFromCurrentSchema', 'useClassConstant', 'enableI18N', 'standardizeCapitals', 'singularize'],
124133
'boolean'
125134
],
126135
[['messageCategory'], 'validateMessageCategory', 'skipOnEmpty' => false],
@@ -143,6 +152,7 @@ public function attributeLabels()
143152
'generateRelations' => 'Generate Relations',
144153
'generateJunctionRelationMode' => 'Generate Junction Relations As',
145154
'generateRelationsFromCurrentSchema' => 'Generate Relations from Current Schema',
155+
'useClassConstant' => 'Use `::class`',
146156
'generateLabelsFromComments' => 'Generate Labels from DB Comments',
147157
'generateQuery' => 'Generate ActiveQuery',
148158
'queryNs' => 'ActiveQuery Namespace',
@@ -184,6 +194,7 @@ class.',
184194
Make sure you also generate the junction models when using the "Via Model" option.
185195
',
186196
'generateRelationsFromCurrentSchema' => 'This indicates whether the generator should generate relations from current schema or from all available schemas.',
197+
'useClassConstant' => 'Use the `::class` constant instead of the `::className()` method.',
187198
'generateLabelsFromComments' => 'This indicates whether the generator should generate attribute labels
188199
by using the comments of the corresponding DB columns.',
189200
'useTablePrefix' => 'This indicates whether the table name returned by the generated ActiveRecord class
@@ -237,7 +248,7 @@ public function requiredTemplates()
237248
public function stickyAttributes()
238249
{
239250
return array_merge(
240-
parent::stickyAttributes(),
251+
parent::stickyAttributes(),
241252
[
242253
'ns',
243254
'db',
@@ -249,6 +260,7 @@ public function stickyAttributes()
249260
'queryBaseClass',
250261
'useTablePrefix',
251262
'generateQuery',
263+
'useClassConstant',
252264
]
253265
);
254266
}
@@ -507,14 +519,15 @@ public function generateRules($table)
507519
continue;
508520
}
509521
$refClassName = $this->generateClassName($refTable);
522+
$refClassNameResolution = $this->generateClassNameResolution($refClassName);
510523
unset($refs[0]);
511524
$attributes = implode("', '", array_keys($refs));
512525
$targetAttributes = [];
513526
foreach ($refs as $key => $value) {
514527
$targetAttributes[] = "'$key' => '$value'";
515528
}
516529
$targetAttributes = implode(', ', $targetAttributes);
517-
$rules[] = "[['$attributes'], 'exist', 'skipOnError' => true, 'targetClass' => $refClassName::className(), 'targetAttribute' => [$targetAttributes]]";
530+
$rules[] = "[['$attributes'], 'exist', 'skipOnError' => true, 'targetClass' => $refClassNameResolution, 'targetAttribute' => [$targetAttributes]]";
518531
}
519532

520533
return $rules;
@@ -531,13 +544,16 @@ private function generateManyManyRelations($table, $fks, $relations)
531544
{
532545
$db = $this->getDbConnection();
533546

547+
534548
foreach ($fks as $pair) {
535549
list($firstKey, $secondKey) = $pair;
536550
$table0 = $firstKey[0][0];
537551
$table1 = $secondKey[0][0];
538552
unset($firstKey[0][0], $secondKey[0][0]);
539553
$className0 = $this->generateClassName($table0);
540554
$className1 = $this->generateClassName($table1);
555+
$className0Resolution = $this->generateClassNameResolution($className0);
556+
$className1Resolution = $this->generateClassNameResolution($className1);
541557
$table0Schema = $db->getTableSchema($table0);
542558
$table1Schema = $db->getTableSchema($table1);
543559

@@ -550,7 +566,7 @@ private function generateManyManyRelations($table, $fks, $relations)
550566
$relationName = $this->generateRelationName($relations, $table0Schema, key($secondKey[0]), true);
551567
if ($this->generateJunctionRelationMode === self::JUNCTION_RELATION_VIA_TABLE) {
552568
$relations[$table0Schema->fullName][$relationName] = [
553-
"return \$this->hasMany($className1::className(), $link)->viaTable('"
569+
"return \$this->hasMany($className1Resolution, $link)->viaTable('"
554570
. $this->generateTableName($table->name) . "', " . $this->generateRelationLink($firstKey[0]) . ');',
555571
$className1,
556572
true,
@@ -567,7 +583,7 @@ private function generateManyManyRelations($table, $fks, $relations)
567583
throw new Exception('Foreign key for junction table not found.');
568584
}
569585
$relations[$table0Schema->fullName][$relationName] = [
570-
"return \$this->hasMany($className1::className(), $link)->via('"
586+
"return \$this->hasMany($className1Resolution, $link)->via('"
571587
. lcfirst($foreignRelationName) . "');",
572588
$className1,
573589
true,
@@ -578,7 +594,7 @@ private function generateManyManyRelations($table, $fks, $relations)
578594
$relationName = $this->generateRelationName($relations, $table1Schema, key($firstKey[0]), true);
579595
if ($this->generateJunctionRelationMode === self::JUNCTION_RELATION_VIA_TABLE) {
580596
$relations[$table1Schema->fullName][$relationName] = [
581-
"return \$this->hasMany($className0::className(), $link)->viaTable('"
597+
"return \$this->hasMany($className0Resolution, $link)->viaTable('"
582598
. $this->generateTableName($table->name) . "', " . $this->generateRelationLink($secondKey[0]) . ');',
583599
$className0,
584600
true,
@@ -595,7 +611,7 @@ private function generateManyManyRelations($table, $fks, $relations)
595611
throw new Exception('Foreign key for junction table not found.');
596612
}
597613
$relations[$table1Schema->fullName][$relationName] = [
598-
"return \$this->hasMany($className0::className(), $link)->via('"
614+
"return \$this->hasMany($className0Resolution, $link)->via('"
599615
. lcfirst($foreignRelationName) . "');",
600616
$className0,
601617
true,
@@ -657,6 +673,7 @@ protected function generateRelations()
657673
foreach ($schemaNames as $schemaName) {
658674
foreach ($db->getSchema()->getTableSchemas($schemaName) as $table) {
659675
$className = $this->generateClassName($table->fullName);
676+
$classNameResolution = $this->generateClassNameResolution($className);
660677
foreach ($table->foreignKeys as $foreignKey => $refs) {
661678
$refTable = $refs[0];
662679
$refTableSchema = $db->getTableSchema($refTable);
@@ -667,12 +684,13 @@ protected function generateRelations()
667684
unset($refs[0]);
668685
$fks = array_keys($refs);
669686
$refClassName = $this->generateClassName($refTable);
687+
$refClassNameResolution = $this->generateClassNameResolution($refClassName);
670688

671689
// Add relation for this table
672690
$link = $this->generateRelationLink(array_flip($refs));
673691
$relationName = $this->generateRelationName($relations, $table, $fks[0], false);
674692
$relations[$table->fullName][$relationName] = [
675-
"return \$this->hasOne($refClassName::className(), $link);",
693+
"return \$this->hasOne($refClassNameResolution, $link);",
676694
$refClassName,
677695
false,
678696
$table->fullName . '.' . $foreignKey
@@ -683,7 +701,7 @@ protected function generateRelations()
683701
$link = $this->generateRelationLink($refs);
684702
$relationName = $this->generateRelationName($relations, $refTableSchema, $className, $hasMany);
685703
$relations[$refTableSchema->fullName][$relationName] = [
686-
"return \$this->" . ($hasMany ? 'hasMany' : 'hasOne') . "($className::className(), $link);",
704+
"return \$this->" . ($hasMany ? 'hasMany' : 'hasOne') . "($classNameResolution, $link);",
687705
$className,
688706
$hasMany,
689707
$table->fullName . '.' . $foreignKey
@@ -1146,4 +1164,16 @@ protected function isColumnAutoIncremental($table, $columns)
11461164

11471165
return false;
11481166
}
1167+
1168+
/**
1169+
* Returns the class name resolution
1170+
* @param string $class
1171+
* @return string
1172+
* @see $useClassConstant
1173+
* @since 2.2.5
1174+
*/
1175+
protected function generateClassNameResolution($class)
1176+
{
1177+
return $class . '::class' . ($this->useClassConstant ? '' : 'Name()');
1178+
}
11491179
}

src/generators/model/form.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
Generator::JUNCTION_RELATION_VIA_MODEL => 'Via Model',
3333
]);
3434
echo $form->field($generator, 'generateRelationsFromCurrentSchema')->checkbox();
35+
echo $form->field($generator, 'useClassConstant')->checkbox();
3536
echo $form->field($generator, 'generateLabelsFromComments')->checkbox();
3637
echo $form->field($generator, 'generateQuery')->checkbox();
3738
echo $form->field($generator, 'queryNs');

tests/SchemaTest.php

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public function testPrefixesGenerator()
3535
public function relationsProvider()
3636
{
3737
return [
38-
['default', 'schema1.*', 5, [
38+
// useClassConstant = false
39+
['default', 'schema1.*', 5, false, [
3940
0 => [ // relations from junction1 table
4041
"\$this->hasOne(Schema1Table1::className(), ['id' => 'table1_id']);",
4142
"\$this->hasOne(Schema1MultiPk::className(), ['id1' => 'multi_pk_id1', 'id2' => 'multi_pk_id2']);",
@@ -76,38 +77,89 @@ public function relationsProvider()
7677
"\$this->hasMany(Schema1Junction2::className(), ['table1_id' => 'id']);",
7778
],
7879
]],
79-
['default', 'schema2.*', 2, [
80+
['default', 'schema2.*', 2, false, [
8081
0 => [
8182
"\$this->hasOne(Schema1Table1::className(), ['fk2' => 'fk1', 'fk1' => 'fk2']);",
8283
"\$this->hasOne(Schema1Table1::className(), ['fk4' => 'fk3', 'fk3' => 'fk4']);",
8384
"\$this->hasOne(Schema2Table2::className(), ['fk5' => 'fk5', 'fk6' => 'fk6']);",
8485
],
8586
]],
87+
88+
// useClassConstant = true
89+
['default', 'schema1.*', 5, true, [
90+
0 => [ // relations from junction1 table
91+
"\$this->hasOne(Schema1Table1::class, ['id' => 'table1_id']);",
92+
"\$this->hasOne(Schema1MultiPk::class, ['id1' => 'multi_pk_id1', 'id2' => 'multi_pk_id2']);",
93+
],
94+
2 => [ // relations from multi_pk table
95+
[
96+
ModelGenerator::JUNCTION_RELATION_VIA_TABLE =>
97+
"\$this->hasMany(Schema1Table1::class, ['id' => 'table1_id'])->viaTable('junction1', ['multi_pk_id1' => 'id1', 'multi_pk_id2' => 'id2']);",
98+
ModelGenerator::JUNCTION_RELATION_VIA_MODEL =>
99+
"\$this->hasMany(Schema1Table1::class, ['id' => 'table1_id'])->via('schema1Junction1s');",
100+
],
101+
[
102+
ModelGenerator::JUNCTION_RELATION_VIA_TABLE =>
103+
"\$this->hasMany(Schema1Table1::class, ['id' => 'table1_id'])->viaTable('junction2', ['multi_pk_id1' => 'id1', 'multi_pk_id2' => 'id2']);",
104+
ModelGenerator::JUNCTION_RELATION_VIA_MODEL =>
105+
"\$this->hasMany(Schema1Table1::class, ['id' => 'table1_id'])->via('schema1Junction2s');",
106+
],
107+
"\$this->hasMany(Schema1Junction1::class, ['multi_pk_id1' => 'id1', 'multi_pk_id2' => 'id2']);",
108+
"\$this->hasMany(Schema1Junction2::class, ['multi_pk_id1' => 'id1', 'multi_pk_id2' => 'id2']);",
109+
],
110+
3 => [ // relations from table1 table
111+
"\$this->hasMany(Schema2Table1::class, ['fk1' => 'fk2', 'fk2' => 'fk1']);",
112+
"\$this->hasMany(Schema2Table1::class, ['fk3' => 'fk4', 'fk4' => 'fk3']);",
113+
"\$this->hasOne(Schema2Table2::class, ['fk1' => 'fk1', 'fk2' => 'fk2']);",
114+
[
115+
ModelGenerator::JUNCTION_RELATION_VIA_TABLE =>
116+
"\$this->hasMany(Schema1MultiPk::class, ['id1' => 'multi_pk_id1', 'id2' => 'multi_pk_id2'])->viaTable('junction1', ['table1_id' => 'id']);",
117+
ModelGenerator::JUNCTION_RELATION_VIA_MODEL =>
118+
"\$this->hasMany(Schema1MultiPk::class, ['id1' => 'multi_pk_id1', 'id2' => 'multi_pk_id2'])->via('schema1Junction1s');",
119+
],
120+
[
121+
ModelGenerator::JUNCTION_RELATION_VIA_TABLE =>
122+
"\$this->hasMany(Schema1MultiPk::class, ['id1' => 'multi_pk_id1', 'id2' => 'multi_pk_id2'])->viaTable('junction2', ['table1_id' => 'id']);",
123+
ModelGenerator::JUNCTION_RELATION_VIA_MODEL =>
124+
"\$this->hasMany(Schema1MultiPk::class, ['id1' => 'multi_pk_id1', 'id2' => 'multi_pk_id2'])->via('schema1Junction2s');",
125+
],
126+
"\$this->hasMany(Schema1Junction1::class, ['table1_id' => 'id']);",
127+
"\$this->hasMany(Schema1Junction2::class, ['table1_id' => 'id']);",
128+
],
129+
]],
130+
['default', 'schema2.*', 2, true, [
131+
0 => [
132+
"\$this->hasOne(Schema1Table1::class, ['fk2' => 'fk1', 'fk1' => 'fk2']);",
133+
"\$this->hasOne(Schema1Table1::class, ['fk4' => 'fk3', 'fk3' => 'fk4']);",
134+
"\$this->hasOne(Schema2Table2::class, ['fk5' => 'fk5', 'fk6' => 'fk6']);",
135+
],
136+
]],
86137
];
87138
}
88139

89140
/**
90141
* @dataProvider relationsProvider
91142
*/
92-
public function testViaTableRelationsGenerator($template, $tableName, $filesCount, $relationSets)
143+
public function testViaTableRelationsGenerator($template, $tableName, $filesCount, $useClassConstant, $relationSets)
93144
{
94-
$this->relationsGeneratorTest($template, $tableName, $filesCount, $relationSets, ModelGenerator::JUNCTION_RELATION_VIA_TABLE);
145+
$this->relationsGeneratorTest($template, $tableName, $filesCount, $useClassConstant, $relationSets, ModelGenerator::JUNCTION_RELATION_VIA_TABLE);
95146
}
96147

97148
/**
98149
* @dataProvider relationsProvider
99150
*/
100-
public function testViaModelRelationsGenerator($template, $tableName, $filesCount, $relationSets)
151+
public function testViaModelRelationsGenerator($template, $tableName, $filesCount, $useClassConstant, $relationSets)
101152
{
102-
$this->relationsGeneratorTest($template, $tableName, $filesCount, $relationSets, ModelGenerator::JUNCTION_RELATION_VIA_MODEL);
153+
$this->relationsGeneratorTest($template, $tableName, $filesCount, $useClassConstant, $relationSets, ModelGenerator::JUNCTION_RELATION_VIA_MODEL);
103154
}
104155

105-
protected function relationsGeneratorTest($template, $tableName, $filesCount, $relationSets, $generateViaRelationMode)
156+
protected function relationsGeneratorTest($template, $tableName, $filesCount, $useClassConstant, $relationSets, $generateViaRelationMode)
106157
{
107158
$generator = new ModelGenerator();
108159
$generator->template = $template;
109160
$generator->tableName = $tableName;
110161
$generator->generateRelationsFromCurrentSchema = false;
162+
$generator->useClassConstant = $useClassConstant;
111163
$generator->generateJunctionRelationMode = $generateViaRelationMode;
112164

113165
$files = $generator->generate();

0 commit comments

Comments
 (0)