1final class ApplicationController
2{
3 public function store(Request $request, Job $job): RedirectResponse
4 {
5 $request->validate(['cv' => ['required', 'file', 'mimes:pdf']]);
6
7 if ($job->status !== 'published') {
8 return back()->withErrors('Вакансію закрито');
9 }
10
11 if ($job->applications()->where('user_id', $request->user()->id)->exists()) {
12 return back()->withErrors('Ви вже відгукнулись');
13 }
14
15 $application = $job->applications()->create([
16 'user_id' => $request->user()->id,
17 'cv_path' => $request->file('cv')->store('cvs'),
18 ]);
19
20 Mail::to($job->company->email)->send(new NewApplicationMail($application));
21
22 return back()->with('status', 'Відгук надіслано');
23 }
24}
1<?php
2
3final class Job
4{
5 /** @var list<int> */
6 private array $candidates = [];
7
8 public function __construct(public readonly int $id, public readonly string $title, private bool $open = true) {}
9
101 public function accept(int $candidateId): void
11 {
12 if (! $this->open) {
13 throw new DomainException('вакансію закрито');
14 }
15 if (in_array($candidateId, $this->candidates, true)) {
16 throw new DomainException('ви вже відгукнулись');
17 }
18 $this->candidates[] = $candidateId;
19 }
20}
21
22final class InMemoryJobs
23{
24 /** @param array<int, Job> $jobs */
25 public function __construct(private array $jobs) {}
26
27 public function get(int $id): Job { return $this->jobs[$id]; }
28 public function save(Job $job): void { $this->jobs[$job->id] = $job; }
29}
30
312final class ApplyToJob
32{
33 public function __construct(private InMemoryJobs $jobs, private Closure $notify) {}
34
35 public function __invoke(int $jobId, int $candidateId, string $cv): void
36 {
37 $job = $this->jobs->get($jobId);
38 $job->accept($candidateId);
39 $this->jobs->save($job);
40 ($this->notify)("новий відгук на «{$job->title}», резюме {$cv}");
41 }
42}
43
443$apply = new ApplyToJob(
45 new InMemoryJobs([7 => new Job(7, 'Middle Laravel Developer'), 8 => new Job(8, 'PHP Team Lead', open: false)]),
46 fn (string $text) => print " лист роботодавцю: {$text}\n",
47);
48
49$requests = [
50 ['сайт', 7, 101, 'olena.pdf'],
51 ['Telegram-бот', 7, 101, 'olena.pdf'],
52 ['Telegram-бот', 8, 102, 'taras.pdf'],
53];
54
554foreach ($requests as [$channel, $jobId, $candidateId, $cv]) {
56 try {
57 $apply($jobId, $candidateId, $cv);
58 echo "{$channel}: відгук надіслано\n";
59 } catch (DomainException $e) {
60 echo "{$channel}: відмова, {$e->getMessage()}\n";
61 }
62}