1.
Сервисы - это вспомогательный код, перед моделью, который вы выносите из контроллера.
Пример. Сами сервисы не должны посылать запросы напрямую в базу. Для это го делается отдельный
репозиторий, который передается через конструктор в сервис.
2. Сервисы подключаются в контроллер через конструктор и обращаются к ним как
$this->userService->create($userFrom или $userDto);
3. Делить сервисы можно хоть на каждое действие (UseCase)
..../Service/User/Create/Service.php
всё зависит от вашей архитектуры. Выносите тогда, когда кода в сервисе становится много. Либо сразу.
Можете ещё почитать это
Архитектура приложения. Как сделать независимые модули (сервисы)? и посмотреть тот репозиторий из github, который вставлял в качестве примера.
Ваш код можно переписать так: Исключил контроллер и PageRepository
class UserService
{
public $users;
public $pages;
public function __construct(UserRepository $users, PageRepository $pages)
{
$this->users = $users;
$this->pages = $pages;
}
public function createUser(CreateForm $form) : void
{
if($this->users->existsByEmail($form->email)) {
thow new DomainExeption('Пользователь уже существует!')
}
$user = new User([
'username' => $form->username,
'name' => $form->name,
'email' => $form->email
]);
$page = new Page([
'name' => $form->page->name
]);
...
$transaction->begin();
try{
$this->users->save($user);
$this->pages->save($page);
$transaction->commit();
}
catch{
$transaction->rollBack();
}
//PS Транзакцию тоже можно вынести в отдельный сервис.
}
}
class UserRepository
{
public function save(User $user): bool
{
if (!$user->save(false)) {
throw new \RuntimeException('Saving error.');
}
}
public function existsByEmail(string $email): bool
{
return User::find()->andWhere(['email' => $email])->exists();
}
}