From 90fbd0b84ad8abd978eaaa369cd87ada8088d24b Mon Sep 17 00:00:00 2001 From: Mark Scherer Date: Fri, 5 Jun 2026 16:34:12 +0200 Subject: [PATCH 1/4] Assign AllCommand subcommands in the constructor ControllerAllCommand, ModelAllCommand and TemplateAllCommand declared their wrapped subcommand as a non-nullable typed property and assigned it in initialize(). On CakePHP 5.4 BaseCommand::run() builds the option parser before calling initialize(), so buildOptionParser() reads the property while it is still uninitialized: Typed property Bake\Command\ControllerAllCommand::$controllerCommand must not be accessed before initialization Move the assignment into the constructor so the subcommand is available regardless of the lifecycle ordering. The override of initialize() is dropped; the inherited BakeCommand::initialize() (table-locator fallback) still runs. TemplateAllCommand never read the property in buildOptionParser(), so its breakage was latent; the change keeps the three commands consistent. --- src/Command/ControllerAllCommand.php | 11 +++++++---- src/Command/ModelAllCommand.php | 11 +++++++---- src/Command/TemplateAllCommand.php | 11 +++++++---- .../Command/ControllerAllCommandTest.php | 16 ++++++++++++++++ tests/TestCase/Command/ModelAllCommandTest.php | 16 ++++++++++++++++ .../TestCase/Command/TemplateAllCommandTest.php | 16 ++++++++++++++++ 6 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/Command/ControllerAllCommand.php b/src/Command/ControllerAllCommand.php index 43ffb3ca..73179725 100644 --- a/src/Command/ControllerAllCommand.php +++ b/src/Command/ControllerAllCommand.php @@ -18,6 +18,7 @@ use Bake\Utility\TableScanner; use Cake\Console\Arguments; +use Cake\Console\CommandFactoryInterface; use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOptionParser; use Cake\Datasource\ConnectionManager; @@ -41,13 +42,15 @@ public static function defaultName(): string } /** - * initialize + * The subcommand is assigned in the constructor (not initialize()) because + * buildOptionParser() runs before initialize() and reads it. * - * @return void + * @param \Cake\Console\CommandFactoryInterface|null $factory Command factory instance. */ - public function initialize(): void + public function __construct(?CommandFactoryInterface $factory = null) { - parent::initialize(); + parent::__construct($factory); + $this->controllerCommand = new ControllerCommand(); } diff --git a/src/Command/ModelAllCommand.php b/src/Command/ModelAllCommand.php index 2bbae1a7..51faf8f1 100644 --- a/src/Command/ModelAllCommand.php +++ b/src/Command/ModelAllCommand.php @@ -18,6 +18,7 @@ use Bake\Utility\TableScanner; use Cake\Console\Arguments; +use Cake\Console\CommandFactoryInterface; use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOptionParser; use Cake\Datasource\ConnectionManager; @@ -41,13 +42,15 @@ public static function defaultName(): string } /** - * initialize + * The subcommand is assigned in the constructor (not initialize()) because + * buildOptionParser() runs before initialize() and reads it. * - * @return void + * @param \Cake\Console\CommandFactoryInterface|null $factory Command factory instance. */ - public function initialize(): void + public function __construct(?CommandFactoryInterface $factory = null) { - parent::initialize(); + parent::__construct($factory); + $this->modelCommand = new ModelCommand(); } diff --git a/src/Command/TemplateAllCommand.php b/src/Command/TemplateAllCommand.php index 0a1c72e5..953d3c33 100644 --- a/src/Command/TemplateAllCommand.php +++ b/src/Command/TemplateAllCommand.php @@ -18,6 +18,7 @@ use Bake\Utility\TableScanner; use Cake\Console\Arguments; +use Cake\Console\CommandFactoryInterface; use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOptionParser; use Cake\Datasource\ConnectionManager; @@ -38,13 +39,15 @@ public static function defaultName(): string } /** - * initialize + * The subcommand is assigned in the constructor (not initialize()) because + * buildOptionParser() runs before initialize() and reads it. * - * @return void + * @param \Cake\Console\CommandFactoryInterface|null $factory Command factory instance. */ - public function initialize(): void + public function __construct(?CommandFactoryInterface $factory = null) { - parent::initialize(); + parent::__construct($factory); + $this->templateCommand = new TemplateCommand(); } diff --git a/tests/TestCase/Command/ControllerAllCommandTest.php b/tests/TestCase/Command/ControllerAllCommandTest.php index 4b70b5d1..e5882a74 100644 --- a/tests/TestCase/Command/ControllerAllCommandTest.php +++ b/tests/TestCase/Command/ControllerAllCommandTest.php @@ -16,9 +16,11 @@ */ namespace Bake\Test\TestCase\Command; +use Bake\Command\ControllerAllCommand; use Bake\Test\App\Model\Table\BakeArticlesTable; use Bake\Test\TestCase\TestCase; use Cake\Console\CommandInterface; +use Cake\Console\ConsoleOptionParser; use Cake\Core\Plugin; use Cake\Utility\Inflector; @@ -91,4 +93,18 @@ public function testExecute(): void 'Test should not be created as options should be forwarded', ); } + + /** + * The option parser is built before initialize() runs, so the wrapped subcommand + * must already be available at that point. Regression test for the subcommand being + * assigned in initialize() instead of the constructor. + * + * @return void + */ + public function testGetOptionParserBeforeInitialize(): void + { + $command = new ControllerAllCommand(); + + $this->assertInstanceOf(ConsoleOptionParser::class, $command->getOptionParser()); + } } diff --git a/tests/TestCase/Command/ModelAllCommandTest.php b/tests/TestCase/Command/ModelAllCommandTest.php index 59bb054f..ae92a2db 100644 --- a/tests/TestCase/Command/ModelAllCommandTest.php +++ b/tests/TestCase/Command/ModelAllCommandTest.php @@ -16,9 +16,11 @@ */ namespace Bake\Test\TestCase\Command; +use Bake\Command\ModelAllCommand; use Bake\Test\TestCase\TestCase; use Bake\Utility\SubsetSchemaCollection; use Cake\Console\CommandInterface; +use Cake\Console\ConsoleOptionParser; use Cake\Datasource\ConnectionManager; use Cake\Utility\Inflector; @@ -99,4 +101,18 @@ public function testExecute(): void 'Table test should not be created as options should be forwarded', ); } + + /** + * The option parser is built before initialize() runs, so the wrapped subcommand + * must already be available at that point. Regression test for the subcommand being + * assigned in initialize() instead of the constructor. + * + * @return void + */ + public function testGetOptionParserBeforeInitialize(): void + { + $command = new ModelAllCommand(); + + $this->assertInstanceOf(ConsoleOptionParser::class, $command->getOptionParser()); + } } diff --git a/tests/TestCase/Command/TemplateAllCommandTest.php b/tests/TestCase/Command/TemplateAllCommandTest.php index c420da3f..1f2d8bc5 100644 --- a/tests/TestCase/Command/TemplateAllCommandTest.php +++ b/tests/TestCase/Command/TemplateAllCommandTest.php @@ -16,9 +16,11 @@ */ namespace Bake\Test\TestCase\Command; +use Bake\Command\TemplateAllCommand; use Bake\Test\TestCase\TestCase; use Bake\Utility\SubsetSchemaCollection; use Cake\Console\CommandInterface; +use Cake\Console\ConsoleOptionParser; use Cake\Core\Plugin; use Cake\Datasource\ConnectionManager; @@ -122,4 +124,18 @@ public function testExecuteOptionForwarding(): void $this->assertFileContains('title', $this->generatedFiles[0]); $this->assertFileNotContains('published', $this->generatedFiles[0]); } + + /** + * The option parser is built before initialize() runs, so the wrapped subcommand + * must already be available at that point. Regression test for the subcommand being + * assigned in initialize() instead of the constructor. + * + * @return void + */ + public function testGetOptionParserBeforeInitialize(): void + { + $command = new TemplateAllCommand(); + + $this->assertInstanceOf(ConsoleOptionParser::class, $command->getOptionParser()); + } } From f73d8485de461fc9c41e840e578b1c7298c28eba Mon Sep 17 00:00:00 2001 From: Mark Scherer Date: Fri, 5 Jun 2026 16:55:59 +0200 Subject: [PATCH 2/4] Lazy-assign subcommand in buildOptionParser for 5.1+ compatibility The constructor approach broke on cakephp/cakephp 5.1, where BaseCommand has no constructor yet (Error: Cannot call constructor via parent::__construct()). Bake supports ^5.1. Assign the wrapped subcommand lazily in buildOptionParser() with ??= instead. buildOptionParser() always runs before execute() on every supported version, and on 5.4 it runs before initialize() too, so the property is always set before use regardless of lifecycle ordering. ??= is safe on an uninitialized typed property and idempotent across repeated parser builds. --- src/Command/ControllerAllCommand.php | 19 +++++-------------- src/Command/ModelAllCommand.php | 19 +++++-------------- src/Command/TemplateAllCommand.php | 19 +++++-------------- 3 files changed, 15 insertions(+), 42 deletions(-) diff --git a/src/Command/ControllerAllCommand.php b/src/Command/ControllerAllCommand.php index 73179725..c1bc2009 100644 --- a/src/Command/ControllerAllCommand.php +++ b/src/Command/ControllerAllCommand.php @@ -18,7 +18,6 @@ use Bake\Utility\TableScanner; use Cake\Console\Arguments; -use Cake\Console\CommandFactoryInterface; use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOptionParser; use Cake\Datasource\ConnectionManager; @@ -41,19 +40,6 @@ public static function defaultName(): string return 'bake controller all'; } - /** - * The subcommand is assigned in the constructor (not initialize()) because - * buildOptionParser() runs before initialize() and reads it. - * - * @param \Cake\Console\CommandFactoryInterface|null $factory Command factory instance. - */ - public function __construct(?CommandFactoryInterface $factory = null) - { - parent::__construct($factory); - - $this->controllerCommand = new ControllerCommand(); - } - /** * Execute the command. * @@ -85,6 +71,11 @@ public function execute(Arguments $args, ConsoleIo $io): ?int */ protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser { + // Assigned here (not initialize()) because on CakePHP 5.4+ the parser is built + // before initialize() runs, while older versions build it after. ??= keeps it + // safe under either ordering and idempotent across repeated calls. + $this->controllerCommand ??= new ControllerCommand(); + $parser = $this->controllerCommand->buildOptionParser($parser); $parser ->setDescription('Bake all controller files with tests.') diff --git a/src/Command/ModelAllCommand.php b/src/Command/ModelAllCommand.php index 51faf8f1..8730e99d 100644 --- a/src/Command/ModelAllCommand.php +++ b/src/Command/ModelAllCommand.php @@ -18,7 +18,6 @@ use Bake\Utility\TableScanner; use Cake\Console\Arguments; -use Cake\Console\CommandFactoryInterface; use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOptionParser; use Cake\Datasource\ConnectionManager; @@ -41,19 +40,6 @@ public static function defaultName(): string return 'bake model all'; } - /** - * The subcommand is assigned in the constructor (not initialize()) because - * buildOptionParser() runs before initialize() and reads it. - * - * @param \Cake\Console\CommandFactoryInterface|null $factory Command factory instance. - */ - public function __construct(?CommandFactoryInterface $factory = null) - { - parent::__construct($factory); - - $this->modelCommand = new ModelCommand(); - } - /** * Gets the option parser instance and configures it. * @@ -62,6 +48,11 @@ public function __construct(?CommandFactoryInterface $factory = null) */ protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser { + // Assigned here (not initialize()) because on CakePHP 5.4+ the parser is built + // before initialize() runs, while older versions build it after. ??= keeps it + // safe under either ordering and idempotent across repeated calls. + $this->modelCommand ??= new ModelCommand(); + $parser = $this->modelCommand->buildOptionParser($parser); $parser ->setDescription('Bake all model files with associations and validation.') diff --git a/src/Command/TemplateAllCommand.php b/src/Command/TemplateAllCommand.php index 953d3c33..2c7ff454 100644 --- a/src/Command/TemplateAllCommand.php +++ b/src/Command/TemplateAllCommand.php @@ -18,7 +18,6 @@ use Bake\Utility\TableScanner; use Cake\Console\Arguments; -use Cake\Console\CommandFactoryInterface; use Cake\Console\ConsoleIo; use Cake\Console\ConsoleOptionParser; use Cake\Datasource\ConnectionManager; @@ -38,19 +37,6 @@ public static function defaultName(): string return 'bake template all'; } - /** - * The subcommand is assigned in the constructor (not initialize()) because - * buildOptionParser() runs before initialize() and reads it. - * - * @param \Cake\Console\CommandFactoryInterface|null $factory Command factory instance. - */ - public function __construct(?CommandFactoryInterface $factory = null) - { - parent::__construct($factory); - - $this->templateCommand = new TemplateCommand(); - } - /** * Execute the command. * @@ -88,6 +74,11 @@ public function execute(Arguments $args, ConsoleIo $io): int */ protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser { + // Assigned here (not initialize()) because on CakePHP 5.4+ the parser is built + // before initialize() runs, while older versions build it after. buildOptionParser() + // always runs before execute(), so this guarantees the subcommand is available there. + $this->templateCommand ??= new TemplateCommand(); + $parser = $this->_setCommonOptions($parser); $parser ->setDescription('Bake all view template files.') From 81ec4414421b0acdca59ceced3dec8d1230c2f60 Mon Sep 17 00:00:00 2001 From: ADmad Date: Wed, 10 Jun 2026 13:53:40 +0530 Subject: [PATCH 3/4] Generate enums with EnumLabelTrait (#1090) * Generate enums with EnumLabelTrait * update phpstan ignores --- composer.json | 8 ++++---- phpstan-baseline.neon | 6 ------ src/BakePlugin.php | 3 +-- src/Command/CellCommand.php | 3 +-- src/Command/CommandCommand.php | 3 +-- src/Command/EnumCommand.php | 3 +-- src/Command/SimpleBakeCommand.php | 3 +-- src/View/BakeView.php | 1 - templates/bake/Model/enum.twig | 12 +++--------- tests/comparisons/Model/testBakeEnum.php | 10 ++-------- tests/comparisons/Model/testBakeEnumBackedInt.php | 10 ++-------- .../Model/testBakeEnumBackedIntWithCases.php | 12 +++--------- .../Model/testBakeEnumBackedWithCases.php | 12 +++--------- .../Model/testBakeTableWithEnumConfig.php | 12 +++--------- .../App/Model/Enum/BakeUserNullableGender.php | 12 +++--------- 15 files changed, 28 insertions(+), 82 deletions(-) diff --git a/composer.json b/composer.json index 352018c4..c2ebe37e 100644 --- a/composer.json +++ b/composer.json @@ -22,16 +22,16 @@ "source": "https://github.com/cakephp/bake" }, "require": { - "php": ">=8.1", - "brick/varexporter": "^0.6.0 || ^0.7.0", - "cakephp/cakephp": "^5.1", + "php": ">=8.2", + "brick/varexporter": "^0.7.0", + "cakephp/cakephp": "dev-5.next as 5.4.0", "cakephp/twig-view": "^2.0.2", "nikic/php-parser": "^5.0.0" }, "require-dev": { "cakephp/cakephp-codesniffer": "^5.0.0", "cakephp/debug_kit": "^5.0.0", - "phpunit/phpunit": "^10.5.40 || ^11.5.20 || ^12.2.4 || ^13.0" + "phpunit/phpunit": "^11.5.20 || ^12.2.4 || ^13.0" }, "autoload": { "psr-4": { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e45840cf..de4a29d8 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,11 +1,5 @@ parameters: ignoreErrors: - - - message: '#^Method Bake\\BakePlugin\:\:bootstrap\(\) has parameter \$app with generic interface Cake\\Core\\PluginApplicationInterface but does not specify its types\: TSubject$#' - identifier: missingType.generics - count: 1 - path: src/BakePlugin.php - - message: '#^Instanceof between mixed and Cake\\Chronos\\Chronos will always evaluate to false\.$#' identifier: instanceof.alwaysFalse diff --git a/src/BakePlugin.php b/src/BakePlugin.php index e2ce6b65..ed8cc035 100644 --- a/src/BakePlugin.php +++ b/src/BakePlugin.php @@ -109,8 +109,7 @@ protected function discoverCommands(CommandCollection $commands): CommandCollect * * @param string $namespace The namespace classes are expected to be in. * @param string $path The path to look in. - * @return array - * @phpstan-return array> + * @return array> */ protected function findInPath(string $namespace, string $path): array { diff --git a/src/Command/CellCommand.php b/src/Command/CellCommand.php index c0fb6dc5..739b9991 100644 --- a/src/Command/CellCommand.php +++ b/src/Command/CellCommand.php @@ -59,8 +59,7 @@ public function template(): string * Get template data. * * @param \Cake\Console\Arguments $arguments Arguments object. - * @return array - * @phpstan-return array + * @return array */ public function templateData(Arguments $arguments): array { diff --git a/src/Command/CommandCommand.php b/src/Command/CommandCommand.php index 8612f330..00c4f49b 100644 --- a/src/Command/CommandCommand.php +++ b/src/Command/CommandCommand.php @@ -57,8 +57,7 @@ public function template(): string * Get template data. * * @param \Cake\Console\Arguments $arguments Arguments object. - * @return array - * @phpstan-return array + * @return array */ public function templateData(Arguments $arguments): array { diff --git a/src/Command/EnumCommand.php b/src/Command/EnumCommand.php index 5eee0d0e..52e2bf9b 100644 --- a/src/Command/EnumCommand.php +++ b/src/Command/EnumCommand.php @@ -61,8 +61,7 @@ public function template(): string * Get template data. * * @param \Cake\Console\Arguments $arguments The arguments for the command - * @return array - * @phpstan-return array + * @return array */ public function templateData(Arguments $arguments): array { diff --git a/src/Command/SimpleBakeCommand.php b/src/Command/SimpleBakeCommand.php index a9667a22..59dcbc5c 100644 --- a/src/Command/SimpleBakeCommand.php +++ b/src/Command/SimpleBakeCommand.php @@ -53,8 +53,7 @@ abstract public function template(): string; * Get template data. * * @param \Cake\Console\Arguments $arguments The arguments for the command - * @return array - * @phpstan-return array + * @return array */ public function templateData(Arguments $arguments): array { diff --git a/src/View/BakeView.php b/src/View/BakeView.php index 99a77010..b6a6abb4 100644 --- a/src/View/BakeView.php +++ b/src/View/BakeView.php @@ -116,7 +116,6 @@ public function dispatchEvent(string $name, array $data = [], ?object $subject = { $name = (string)preg_replace('/^View\./', 'Bake.', $name); - /** @phpstan-ignore-next-line missingType.generics */ return parent::dispatchEvent($name, $data, $subject); } diff --git a/templates/bake/Model/enum.twig b/templates/bake/Model/enum.twig index 83f48243..2ef141ee 100644 --- a/templates/bake/Model/enum.twig +++ b/templates/bake/Model/enum.twig @@ -17,22 +17,16 @@ namespace: "#{namespace}\\Model\\Enum", classImports: [ 'Cake\\Database\\Type\\EnumLabelInterface', - 'Cake\\Utility\\Inflector', + 'Cake\\Database\\Type\\EnumLabelTrait', ], }) }} {{ DocBlock.classDescription(name, 'Enum', [])|raw }} enum {{ name }}: {{ backingType }} implements EnumLabelInterface { + use EnumLabelTrait; {% if cases %} - {{ Bake.concat('\n ', cases) }} + {{ Bake.concat('\n ', cases) }} {% endif %} - /** - * @return string - */ - public function label(): string - { - return Inflector::humanize(Inflector::underscore($this->name)); - } } diff --git a/tests/comparisons/Model/testBakeEnum.php b/tests/comparisons/Model/testBakeEnum.php index 41c6faea..cdab77f6 100644 --- a/tests/comparisons/Model/testBakeEnum.php +++ b/tests/comparisons/Model/testBakeEnum.php @@ -4,18 +4,12 @@ namespace Bake\Test\App\Model\Enum; use Cake\Database\Type\EnumLabelInterface; -use Cake\Utility\Inflector; +use Cake\Database\Type\EnumLabelTrait; /** * FooBar Enum */ enum FooBar: string implements EnumLabelInterface { - /** - * @return string - */ - public function label(): string - { - return Inflector::humanize(Inflector::underscore($this->name)); - } + use EnumLabelTrait; } diff --git a/tests/comparisons/Model/testBakeEnumBackedInt.php b/tests/comparisons/Model/testBakeEnumBackedInt.php index c0c0648c..0fbe2b07 100644 --- a/tests/comparisons/Model/testBakeEnumBackedInt.php +++ b/tests/comparisons/Model/testBakeEnumBackedInt.php @@ -4,18 +4,12 @@ namespace Bake\Test\App\Model\Enum; use Cake\Database\Type\EnumLabelInterface; -use Cake\Utility\Inflector; +use Cake\Database\Type\EnumLabelTrait; /** * FooBar Enum */ enum FooBar: int implements EnumLabelInterface { - /** - * @return string - */ - public function label(): string - { - return Inflector::humanize(Inflector::underscore($this->name)); - } + use EnumLabelTrait; } diff --git a/tests/comparisons/Model/testBakeEnumBackedIntWithCases.php b/tests/comparisons/Model/testBakeEnumBackedIntWithCases.php index fcd88e07..d5beba07 100644 --- a/tests/comparisons/Model/testBakeEnumBackedIntWithCases.php +++ b/tests/comparisons/Model/testBakeEnumBackedIntWithCases.php @@ -4,22 +4,16 @@ namespace Bake\Test\App\Model\Enum; use Cake\Database\Type\EnumLabelInterface; -use Cake\Utility\Inflector; +use Cake\Database\Type\EnumLabelTrait; /** * FooBar Enum */ enum FooBar: int implements EnumLabelInterface { + use EnumLabelTrait; + case Foo = 0; case Bar = 1; case BarBaz = 9; - - /** - * @return string - */ - public function label(): string - { - return Inflector::humanize(Inflector::underscore($this->name)); - } } diff --git a/tests/comparisons/Model/testBakeEnumBackedWithCases.php b/tests/comparisons/Model/testBakeEnumBackedWithCases.php index 403e8fda..a13c1378 100644 --- a/tests/comparisons/Model/testBakeEnumBackedWithCases.php +++ b/tests/comparisons/Model/testBakeEnumBackedWithCases.php @@ -4,22 +4,16 @@ namespace Bake\Test\App\Model\Enum; use Cake\Database\Type\EnumLabelInterface; -use Cake\Utility\Inflector; +use Cake\Database\Type\EnumLabelTrait; /** * FooBar Enum */ enum FooBar: string implements EnumLabelInterface { + use EnumLabelTrait; + case Foo = 'foo'; case Bar = 'b'; case BarBaz = 'bar_baz'; - - /** - * @return string - */ - public function label(): string - { - return Inflector::humanize(Inflector::underscore($this->name)); - } } diff --git a/tests/comparisons/Model/testBakeTableWithEnumConfig.php b/tests/comparisons/Model/testBakeTableWithEnumConfig.php index 1287d1ac..be913fa3 100644 --- a/tests/comparisons/Model/testBakeTableWithEnumConfig.php +++ b/tests/comparisons/Model/testBakeTableWithEnumConfig.php @@ -4,22 +4,16 @@ namespace Bake\Test\App\Model\Enum; use Cake\Database\Type\EnumLabelInterface; -use Cake\Utility\Inflector; +use Cake\Database\Type\EnumLabelTrait; /** * BakeUserNullableGender Enum */ enum BakeUserNullableGender: string implements EnumLabelInterface { + use EnumLabelTrait; + case Male = 'male'; case Female = 'female'; case Diverse = 'diverse'; - - /** - * @return string - */ - public function label(): string - { - return Inflector::humanize(Inflector::underscore($this->name)); - } } diff --git a/tests/test_app/App/Model/Enum/BakeUserNullableGender.php b/tests/test_app/App/Model/Enum/BakeUserNullableGender.php index 1287d1ac..be913fa3 100644 --- a/tests/test_app/App/Model/Enum/BakeUserNullableGender.php +++ b/tests/test_app/App/Model/Enum/BakeUserNullableGender.php @@ -4,22 +4,16 @@ namespace Bake\Test\App\Model\Enum; use Cake\Database\Type\EnumLabelInterface; -use Cake\Utility\Inflector; +use Cake\Database\Type\EnumLabelTrait; /** * BakeUserNullableGender Enum */ enum BakeUserNullableGender: string implements EnumLabelInterface { + use EnumLabelTrait; + case Male = 'male'; case Female = 'female'; case Diverse = 'diverse'; - - /** - * @return string - */ - public function label(): string - { - return Inflector::humanize(Inflector::underscore($this->name)); - } } From 75383f9dcfb87cdec8adf28ffa292a62a018a62b Mon Sep 17 00:00:00 2001 From: ADmad Date: Mon, 20 Jul 2026 00:26:34 +0530 Subject: [PATCH 4/4] Bump up deps --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index c2ebe37e..d08c73ef 100644 --- a/composer.json +++ b/composer.json @@ -24,8 +24,8 @@ "require": { "php": ">=8.2", "brick/varexporter": "^0.7.0", - "cakephp/cakephp": "dev-5.next as 5.4.0", - "cakephp/twig-view": "^2.0.2", + "cakephp/cakephp": "^5.4", + "cakephp/twig-view": "^2.1", "nikic/php-parser": "^5.0.0" }, "require-dev": {