A
A
alex4answ2019-11-12 19:39:02
Yii
alex4answ, 2019-11-12 19:39:02

How to properly organize the code, files in the project?

Good afternoon, I started a big project, and realized that I was designing and organizing it very crutch.
For example, for MVC,
there are models:

User - id | name | login ...
Page - id | owner_id | title ...
Setting - id | page_id ...

To implement a thin controller, I create a "Service" for each entity, where I put frequent operations I do, for example:
User Service

class UserService 
{
    public static function createUser(array $data) : bool
    {
    $model = new User();
    ...
    $transaction->begin();
    
    try{
      if($model->save() && PageService::create(...)){
        $transaction->commit();
      }
      else{
        $transaction->rollBack();
      }
    }
    catch{
      $transaction->rollBack();
    }
    
    return true;
    }
}


Page Service

class PageService 
{
    public static function createPage(array $data) : bool
    {
    // Почти тоже самое что в UserService::createUser, только создаются Настройки SettingService::create()...
    return true;
    }
  
  public static function getUserPages(int $user_id): ?ActiveRecord
  {
    return Page::findAll(['owner_id' => $user_id]);
  }
  
  public static function updatePage(int $page_id, array $data): bool
  {
    // обновление
  }
  
  // и тп, все возможные операции
}


Accordingly, at the output we have classes almost completely clogged with static methods, everything is in a
heap
. on the right path, as long as it seems to me that such an organization will be spit in the face.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Maxim, 2019-11-13
@alex4answ

1. Services are helper code before the model that you take out of the controller. Example . The services themselves should not send requests directly to the database. For this, a separate repository is made , which is passed through the constructor to the service.
2. Services are connected to the controller through the constructor and accessed as

$this->userService->create($userFrom или $userDto);

3. You can divide services at least for each action (UseCase),
..../Service/User/Create/Service.phpeverything depends on your architecture. Take out when there is a lot of code in the service. Or right away.
You can also read this Application Architecture. How to make independent modules (services)? and see the repository from github that I inserted as an example.
Your code can be rewritten like this: Removed the controller and 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();
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question