| sidebar_position | 10 |
|---|---|
| title | Custom Fields |
You can extend the UserModel to add custom fields that match your database schema.
:::info When to Use This This guide is for adding new fields beyond the standard user fields. If you just need to map existing database columns to the standard fields, see Database Storage instead. :::
<?php
namespace App\Model;
use ByJG\Authenticate\Model\UserModel;
use ByJG\MicroOrm\Attributes\FieldAttribute;
class CustomUserModel extends UserModel
{
#[FieldAttribute(fieldName: 'phone')]
protected ?string $phone = null;
#[FieldAttribute(fieldName: 'department')]
protected ?string $department = null;
#[FieldAttribute(fieldName: 'title')]
protected ?string $title = null;
#[FieldAttribute(fieldName: 'profile_picture')]
protected ?string $profilePicture = null;
public function __construct(
string $name = "",
string $email = "",
string $username = "",
string $password = "",
string $admin = "no",
string $phone = "",
string $department = ""
) {
parent::__construct($name, $email, $username, $password, $admin);
$this->phone = $phone;
$this->department = $department;
}
public function getPhone(): ?string
{
return $this->phone;
}
public function setPhone(?string $phone): void
{
$this->phone = $phone;
}
public function getDepartment(): ?string
{
return $this->department;
}
public function setDepartment(?string $department): void
{
$this->department = $department;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(?string $title): void
{
$this->title = $title;
}
public function getProfilePicture(): ?string
{
return $this->profilePicture;
}
public function setProfilePicture(?string $profilePicture): void
{
$this->profilePicture = $profilePicture;
}
}Add the custom fields to your users table:
CREATE TABLE users
(
userid INTEGER AUTO_INCREMENT NOT NULL,
name VARCHAR(50),
email VARCHAR(120),
username VARCHAR(15) NOT NULL,
password CHAR(40) NOT NULL,
created_at DATETIME,
updated_at DATETIME,
deleted_at DATETIME,
role VARCHAR(20),
-- Custom fields
phone VARCHAR(20),
department VARCHAR(50),
title VARCHAR(50),
profile_picture VARCHAR(255),
CONSTRAINT pk_users PRIMARY KEY (userid)
) ENGINE=InnoDB;<?php
use ByJG\Authenticate\Enum\LoginField;
use ByJG\Authenticate\Service\UsersService;
use ByJG\Authenticate\Repository\UsersRepository;
use ByJG\Authenticate\Repository\UserPropertiesRepository;
use ByJG\Authenticate\Model\UserPropertiesModel;
use ByJG\AnyDataset\Db\DatabaseExecutor;
use ByJG\AnyDataset\Db\Factory;
use App\Model\CustomUserModel;
// Database connection
$dbDriver = Factory::getDbInstance('mysql://user:password@localhost/database');
$db = DatabaseExecutor::using($dbDriver);
// Initialize repositories with custom model
$usersRepo = new UsersRepository($db, CustomUserModel::class);
$propsRepo = new UserPropertiesRepository($db, UserPropertiesModel::class);
// Create service
$users = new UsersService($usersRepo, $propsRepo, LoginField::Email);
// Using the model directly
$user = new CustomUserModel();
$user->setName('John Doe');
$user->setEmail('john@example.com');
$user->setUsername('johndoe');
$user->setPassword('SecurePass123');
$user->setPhone('+1-555-1234');
$user->setDepartment('Engineering');
$user->setTitle('Senior Developer');
$users->save($user);<?php
$user = $users->getById($userId);
// Access custom fields
echo $user->getName();
echo $user->getPhone();
echo $user->getDepartment();
echo $user->getTitle();<?php
$user = $users->getById($userId);
$user->setDepartment('Sales');
$user->setTitle('Sales Manager');
$users->save($user);You can mark fields as read-only to prevent updates using the ReadOnlyMapper:
<?php
use ByJG\MicroOrm\MapperFunctions\ReadOnlyMapper;
use ByJG\MicroOrm\Attributes\FieldAttribute;
class CustomUserModel extends UserModel
{
// Read-only field - can be set on creation but not updated
#[FieldAttribute(fieldName: 'created_at', updateFunction: ReadOnlyMapper::class, insertFunction: NowUtcMapper::class)]
protected ?string $createdAt = null;
// Read-only custom field
#[FieldAttribute(fieldName: 'phone', updateFunction: ReadOnlyMapper::class)]
protected ?string $phone = null;
}Read-only fields:
- Can be set during creation
- Cannot be updated after creation
- Are ignored during updates
You can transform fields during read/write operations using mappers. See Mappers for details.
For storing JSON data in custom fields:
<?php
use ByJG\MicroOrm\FieldMapping\FieldHandler;
use ByJG\MicroOrm\Attributes\FieldAttribute;
class CustomUserModel extends UserModel
{
#[FieldAttribute(
fieldName: 'metadata',
updateFunction: [FieldHandler::class, 'toJson'],
selectFunction: [FieldHandler::class, 'fromJson']
)]
protected ?array $metadata = null;
}<?php
use ByJG\MicroOrm\FieldMapping\FieldHandler;
use ByJG\MicroOrm\Attributes\FieldAttribute;
class CustomUserModel extends UserModel
{
#[FieldAttribute(
fieldName: 'created_at',
selectFunction: [FieldHandler::class, 'toDate']
)]
protected ?\DateTime $createdAt = null;
}<?php
namespace App;
use ByJG\Authenticate\Enum\LoginField;
use ByJG\Authenticate\Service\UsersService;
use ByJG\Authenticate\Repository\UsersRepository;
use ByJG\Authenticate\Repository\UserPropertiesRepository;
use ByJG\Authenticate\Model\UserPropertiesModel;
use ByJG\AnyDataset\Db\Factory;
use ByJG\AnyDataset\Db\DatabaseExecutor;
use App\Model\CustomUserModel;
// Database connection
$dbDriver = Factory::getDbInstance('mysql://user:password@localhost/database');
$db = DatabaseExecutor::using($dbDriver);
// Initialize repositories with custom model
$usersRepo = new UsersRepository($db, CustomUserModel::class);
$propsRepo = new UserPropertiesRepository($db, UserPropertiesModel::class);
// Initialize user service
$users = new UsersService($usersRepo, $propsRepo, LoginField::Email);
// Create a user
$user = new CustomUserModel();
$user->setName('Jane Smith');
$user->setEmail('jane@example.com');
$user->setUsername('janesmith');
$user->setPassword('SecurePass123');
$user->setPhone('+1-555-5678');
$user->setDepartment('Marketing');
$user->setTitle('Marketing Director');
$savedUser = $users->save($user);
// Retrieve and update
$user = $users->getById($savedUser->getUserid());
$user->setTitle('VP of Marketing');
$users->save($user);| Use Custom Fields When | Use Properties When |
|---|---|
| Field is used frequently | Field is rarely used |
| Field is searched/filtered | Field is key-value metadata |
| Field is fixed schema | Field is dynamic/flexible |
| Better performance needed | Schema flexibility needed |
| Field is required | Field is optional |
- Mappers - Custom field transformations
- Database Storage - Schema configuration
- User Properties - Flexible metadata storage