Skip to content

Commit

Permalink
Add backed enum example.
Browse files Browse the repository at this point in the history
  • Loading branch information
dereuromark committed Nov 2, 2023
1 parent 8fe9a97 commit 2e26e8b
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 1 deletion.
28 changes: 28 additions & 0 deletions config/Migrations/20211014000229_MigrationUserStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
declare(strict_types = 1);

use Migrations\AbstractMigration;

// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR2R.Classes.ClassFileName.NoMatch
class MigrationUserStatus extends AbstractMigration {

/**
* Change Method.
*
* More information on this method is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method
*
* @return void
*/
public function change() {
$this->table('sandbox_users')
->addColumn('status', 'tinyinteger', [
'default' => 0,
'limit' => null,
'null' => false,
])
->update();
}

}
24 changes: 24 additions & 0 deletions plugins/Sandbox/src/Controller/CakeExamplesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Cake\Http\Exception\NotFoundException;
use Cake\I18n\I18n;
use Cake\Utility\Hash;
use Sandbox\Model\Enum\UserStatus;

/**
* @property \Sandbox\Model\Table\AnimalsTable $Animals
Expand All @@ -20,6 +21,29 @@ public function index() {
$this->set(compact('actions'));
}

/**
* @return void
*/
public function enums() {
if ($this->request->is(['post', 'put'])) {
$enum = UserStatus::from((int)$this->request->getData('status'));
$this->Flash->info('Value posted: `' . $this->request->getData('status') . '` (`' . $enum->label() . '`)');
}

$user = $this->fetchTable('Sandbox.SandboxUsers')->find()->first();
if (!$user) {
$user = $this->fetchTable('Sandbox.SandboxUsers')->newEntity([
'username' => 'Example',
'slug' => 'example',
'email' => 'example@example.de',
'password' => '',
]);
$this->fetchTable('Sandbox.SandboxUsers')->saveOrFail($user);
}

$this->set(compact('user'));
}

/**
* @return void
*/
Expand Down
46 changes: 46 additions & 0 deletions plugins/Sandbox/src/Model/Entity/SandboxUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);

namespace Sandbox\Model\Entity;

use Cake\ORM\Entity;

/**
* SandboxUser Entity
*
* @property int $id
* @property \Cake\I18n\DateTime|null $created
* @property \Cake\I18n\DateTime|null $modified
* @property string $username
* @property string $slug
* @property string $password
* @property string $email
* @property int $role_id
* @property \Sandbox\Model\Enum\UserStatus $status
*/
class SandboxUser extends Entity {

/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* @var array<string, bool>
*/
protected array $_accessible = [
'*' => true,
'id' => false,
];

/**
* Fields that are excluded from JSON versions of the entity.
*
* @var array<string>
*/
protected array $_hidden = [
'password',
];

}
16 changes: 16 additions & 0 deletions plugins/Sandbox/src/Model/Enum/UserStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Sandbox\Model\Enum;

enum UserStatus: int
{
case INACTIVE = 0;
case ACTIVE = 1;

/**
* @return string
*/
public function label(): string {
return mb_strtolower($this->name);
}
}
4 changes: 4 additions & 0 deletions plugins/Sandbox/src/Model/Table/SandboxUsersTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Sandbox\Model\Table;

use Cake\Database\Type\EnumType;
use Sandbox\Model\Enum\UserStatus;
use Tools\Model\Table\Table;

class SandboxUsersTable extends Table {
Expand Down Expand Up @@ -32,6 +34,8 @@ class SandboxUsersTable extends Table {
* @return void
*/
public function initialize(array $config): void {
$this->getSchema()->setColumnType('status', EnumType::from(UserStatus::class));

$this->setDisplayField('username');
}

Expand Down
57 changes: 57 additions & 0 deletions plugins/Sandbox/templates/CakeExamples/enums.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php
/**
* @var \App\View\AppView $this
* @var \Sandbox\Model\Entity\SandboxUser $user
*/
?>

<h2>Enums</h2>
<p>
With CakePHP 5 we can now use more native (backed) enums in our apps.
</p>

<p>Let's use the `UserStatus` backed enum (int values and string labels) as it can be found in source code to test it.</p>

<p>First, lets use ::cases() to list all possible enum cases:</p>
<ul>
<?php
$cases = \Sandbox\Model\Enum\UserStatus::cases();
foreach ($cases as $case) {
echo '<li>' . $case->label() . ' (`' . $case->value . '`)</li>';
}
?>
</ul>


<?php if (!empty($result)) {
echo '<b>Result:</b>';
echo pre(h($result));
}?>

<h3>In DB and Forms</h3>
<p>For it to work, we need to assign the database table field to enum type:</p>

<div><pre class="code-snippet"><?php
$text = <<<TXT
// SandboxUsersTable
public function initialize(array \$config): void {
\$this->getSchema()->setColumnType('status', EnumType::from(UserStatus::class));
}
TXT;
echo h($text);
?></pre></div>


<p>Let's load a demo record with the enum included now:</p>

<h4>
<?php echo h($user->username); ?>
</h4>
<p>Status: <?php echo h($user->status->label()); ?></p>


<h4>Submit a form</h4>
<?php echo $this->Form->create($user); ?>
<?php echo $this->Form->control('status'); ?>
<?php echo $this->Form->submit(); ?>
<?php echo $this->Form->end(); ?>
3 changes: 2 additions & 1 deletion plugins/Sandbox/tests/Fixture/SandboxUsersFixture.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class SandboxUsersFixture extends TestFixture {
'password' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null],
'email' => ['type' => 'string', 'length' => 80, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null],
'role_id' => ['type' => 'integer', 'length' => 2, 'unsigned' => false, 'null' => false, 'default' => '0', 'comment' => '', 'precision' => null, 'autoIncrement' => null],
'_constraints' => [
'status' => ['type' => 'integer', 'length' => 2, 'unsigned' => false, 'null' => false, 'default' => '0', 'comment' => '', 'precision' => null, 'autoIncrement' => null],
'_constraints' => [
'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []],
],
'_options' => [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);

namespace Sandbox\Test\TestCase\Model\Table;

use Cake\TestSuite\TestCase;
use Sandbox\Model\Table\SandboxUsersTable;

/**
* Sandbox\Model\Table\SandboxUsersTable Test Case
*/
class SandboxUsersTableTest extends TestCase {

/**
* Test subject
*
* @var \Sandbox\Model\Table\SandboxUsersTable
*/
protected $SandboxUsers;

/**
* Fixtures
*
* @var array<string>
*/
protected array $fixtures = [
'plugin.Sandbox.SandboxUsers',
];

/**
* setUp method
*
* @return void
*/
protected function setUp(): void {
parent::setUp();
$config = $this->getTableLocator()->exists('SandboxUsers') ? [] : ['className' => SandboxUsersTable::class];
$this->SandboxUsers = $this->getTableLocator()->get('SandboxUsers', $config);
}

/**
* tearDown method
*
* @return void
*/
protected function tearDown(): void {
unset($this->SandboxUsers);

parent::tearDown();
}

}

0 comments on commit 2e26e8b

Please sign in to comment.