class User extends DataModel{ /** * Check if user is admin */ protected function getisAdmin(): bool { return FORK_GROUP_ADMIN === $this->group_id; } /** * Check if user is guest */ protected function getisGuest(): bool { return FORK_GROUP_GUEST === $this->group_id || null === $this->group_id || $this->id < 1; } /** * Get link to user profile */ protected function getlink(): ?string { if ($this->isGuest) { return null; } return $this->c->Router->link('User', [ 'id' => $this->id, 'name' => $this->c->Func->friendly($this->username) ]); } /** * Get number of topics per page for this user */ protected function getdisp_topics(): int { $attr = $this->getModelAttr('disp_topics'); if ($attr < 10) { $attr = $this->c->config->i_disp_topics_default; } return $attr; }}
Computed properties are cached after first access. The cache is automatically cleared when dependent properties change.
Extends Model with change tracking for database persistence:
app/Models/DataModel.php
class DataModel extends Model{ protected array $zModFlags = []; // Modified properties protected array $zTrackFlags = []; // Tracking state // Get list of modified properties public function getModified(): array // Check if property was modified public function isModified(string $name): bool // Reset modification flags public function resModified(): void}
$user = $c->users->load(123);// Make changes$user->email = 'newemail@example.com';$user->signature = 'My new signature';// Check what changedif ($user->isModified('email')) { echo 'Email was changed';}// Get all modified properties$modified = $user->getModified();// Result: ['email', 'signature']// Save only modified fields to database$c->users->update($user);// Reset modification tracking$user->resModified();
class User extends DataModel{ protected string $cKey = 'User'; // Properties public int $id; public int $group_id; public string $username; public string $email; public int $num_posts; public int $last_visit; // ... more properties // Computed properties public function getisAdmin(): bool; public function getisGuest(): bool; public function getisAdmMod(): bool; public function getonline(): bool; public function getlink(): ?string; public function getavatar(): ?string; // Methods public function title(): string; public function deleteAvatar(): void; public function isModerator(Model $model): bool;}
$user = $c->user; // Current userif ($user->isGuest) { // Redirect to login} elseif ($user->isAdmin) { // Show admin panel} elseif ($user->isAdmMod) { // Show moderator tools}
class Forum extends DataModel{ protected string $cKey = 'Forum'; // Properties public int $id; public int $parent_forum_id; public string $forum_name; public string $forum_desc; public int $num_topics; public int $num_posts; public int $last_post; // ... more properties // Relationships public function getparent(): ?Forum; public function getsubforums(): array; public function getdescendants(): array; // Computed properties public function getlink(): string; public function getlinkNew(): string; public function getlinkLast(): string; public function getcanCreateTopic(): bool; // Methods public function modAdd(User ...$users): void; public function modDelete(User ...$users): void; public function pageData(): array;}
$forum = $c->forums->get(123);echo $forum->forum_name; // Forum nameecho $forum->link; // Forum URLecho $forum->linkNew; // New posts URL// Parent forumif ($parent = $forum->parent) { echo $parent->forum_name;}// Subforumsforeach ($forum->subforums as $sub) { echo $sub->forum_name; echo $sub->link;}
Managers handle collections and database operations:
class Users extends Manager{ // Load user by ID public function load(int $id): ?User; // Create new user public function create(array $attrs = []): User; // Insert user to database public function insert(User $user): int; // Update user in database public function update(User $user): User; // Delete user from database public function delete(User $user): void; // Get current user public function current(): User;}
protected function getisAdmin(): bool { ... }protected function getlink(): ?string { ... }protected function getsubforums(): array { ... }
Keep Business Logic in Models
Don’t put business logic in controllers. It belongs in models.
// Good - in User modelpublic function canEditPost(Post $post): bool { return $this->id === $post->poster_id || $this->isAdmin || $this->isModerator($post->parent);}