1final class Vacancy
2{
3 public function publish(): void
4 {
5 if ($this->status === 'draft' || $this->status === 'moderation') {
6 $this->status = 'published';
7 $this->publishedAt = new DateTimeImmutable();
8 } elseif ($this->status === 'published') {
9 throw new DomainException('Вакансію вже опубліковано');
10 }
11 }
12
13 public function close(): void
14 {
15 if ($this->status !== 'published') {
16 throw new DomainException('Закрити можна лише опубліковану вакансію');
17 }
18 $this->status = 'closed';
19 }
20
21 public function edit(string $title): void
22 {
23 if ($this->status === 'closed') {
24 throw new DomainException('Закриту вакансію не редагують');
25 }
26 $this->title = $title;
27 }
28}
1<?php
2
31interface VacancyState
4{
5 public function publish(): VacancyState;
6
7 public function close(): VacancyState;
8
9 public function name(): string;
10}
11
122final class Draft implements VacancyState
13{
14 public function publish(): VacancyState { return new Published(); }
15 public function close(): VacancyState { throw new DomainException('Чернетку не закривають, її видаляють'); }
16 public function name(): string { return 'чернетка'; }
17}
18
19final class Published implements VacancyState
20{
21 public function publish(): VacancyState { throw new DomainException('Вакансію вже опубліковано'); }
22 public function close(): VacancyState { return new Closed(); }
23 public function name(): string { return 'опублікована'; }
24}
25
26final class Closed implements VacancyState
27{
28 public function publish(): VacancyState { throw new DomainException('Закриту вакансію не публікують знову'); }
29 public function close(): VacancyState { throw new DomainException('Вакансію вже закрито'); }
30 public function name(): string { return 'закрита'; }
31}
32
333final class Vacancy
34{
35 private VacancyState $state;
36
37 public function __construct(public readonly string $title)
38 {
39 $this->state = new Draft();
40 }
41
42 public function publish(): void { $this->state = $this->state->publish(); }
43 public function close(): void { $this->state = $this->state->close(); }
44 public function status(): string { return $this->state->name(); }
45}
46
47$vacancy = new Vacancy('Middle Laravel Developer, Київ');
48echo "{$vacancy->title}: {$vacancy->status()}\n";
49
504foreach (['publish', 'publish', 'close', 'publish'] as $action) {
51 try {
52 $vacancy->{$action}();
53 echo " {$action}() → {$vacancy->status()}\n";
54 } catch (DomainException $e) {
55 echo " {$action}() відхилено: {$e->getMessage()}\n";
56 }
57}