How to use Repository?

Hello! Learn php, a smooth transition from velosipedisty to best practices. Engineering once the application realized that it would be very appropriate to use the Repository pattern to separate business logic from CRUD + use different repositories for different entities.
Did two interfaces IOUserRepository, IOPostRepository for entities User and Post sootvestvenno.
Classes for working with databases that implement these interfaces MySQLUserRepository and RedisPostRepository themselves the entity classes User and Postthat contain logic (e.g. User->ban(), Post->approve() , etc.)

And once ripe the question, and how to organize the relationship of these entities? Ie if you are using ActiveRecord , I did that User::find(1)->post()->where('is_approved', '0')->first()->approve() (example for ELoquent). One of the outputs I see:
1) In the class User do array $posts
2) In the class RedisPostRepository do method getPostsByUserID($user_id)that returns an array of articles for the user
3) In the load()method of class MySQLUserRepository caused by the above mentioned method to populate the array $posts from paragraph 1, but you need to pass an object of a class that implements IOPostRepository ( in the DI container makes binding interface->class, is used Pimple)
The other, in the database relationship one to many (one User -> many Posts).
It turns out, when you use this pattern to do the connection at the level of repositories ?
PS it is Very possible that I misunderstood the essence of this pattern. If so, please poke his nose in mistakes.
June 7th 19 at 15:37
1 answer
June 7th 19 at 15:39
Solution
themselves the entity classes User and Post that contain logic (e.g. User->ban(), Post->approve (), etc.)
This is not correct, it should be in the service level
It turns out, when you use this pattern to do the connection at the level of repositories ?
right
A transaction to run in services
Ie it turns out that the logic is stored in separate classes of services (which downloaded through the service providers ? ), and the classes User and Post, contain data only, ie just a set of variables ? - arnold_Stehr42 commented on June 7th 19 at 15:42
, +, the set of properties + getters/setters, to be exact - Jayce.Hyatt92 commented on June 7th 19 at 15:45
and yet the essence, the services must not give sushnosti further than the level of DAO (repository) - Jayce.Hyatt92 commented on June 7th 19 at 15:48
yeah, okay. Now, last question, what is the sequence of actions in the controller? ie for example has received a request from the admin to ban the user. In the controller I have:
1) access the repository and download by id\username\etc User entity
2) Give the entity to the service UserService->setUser($user);
3) Perform a logic UseService->ban()
4) return a User entity
5) Retain from repository back (update)
All right?

Or service must access the repository?
UPD: Missed the point about transaction services, so we pass the repository to the service and he retains the\removes from the database using the repository - arnold_Stehr42 commented on June 7th 19 at 15:51
no, the meaning of this
The controller calls the ban($userId) service
The service starts a transaction
The service receives the user with that ID from the repository, updates to that thread or inserts entry on the bath in the repository ( the service may use a lot of repositories at once, and to invoke methods on other services)
The service ends a transaction and throws exception if error
Let's see if Dependency Injection (to give the service the implementation of the required repository), ORM (help for mapping entities to tables)
Ideally, the essence of service anywhere should not be referred, that is encapsulated - Jayce.Hyatt92 commented on June 7th 19 at 15:54
huge thanks, missed the complete picture!!! Details about DI read when I was learning Laravel, so I know how to send REP to the service) While the ORM instead of writing plain SQL, because I want him too pull, and test project allows. If it comes to production, of course ORM will connect, since the repository allows it without pain to do) - arnold_Stehr42 commented on June 7th 19 at 15:57
, take a moment and also I ask ;) you can also make a trait for example is Bannable for the service to the user to add functionality? That is, of a trait have to apply to the service. And how to do it better? - Alanna44 commented on June 7th 19 at 16:00
better to use a separate service for the ban, and the entity is only under these
The entity does not have to leave the level of services - Jayce.Hyatt92 commented on June 7th 19 at 16:03
for the sake of interest found the package for laravale - https://github.com/cybercog/laravel-ban

Yes, there's a service for the ban of course, but the trait just makes the interface to the service is more simple and does not violate any principles. Just in the layer of Annex you already added the user to the functionality of the service, and you can not add, and using the service directly. So the wave standards.

And by the way you wrote that in service it is necessary to transfer id. But better interface is to transfer as id us is very limiting. Here, for example, the user implements the interface Bannable, which I think is much more correct. - Alanna44 commented on June 7th 19 at 16:06
that's the point, logic must be in service, the remaining components must use only the API interface for the service, it is desirable that all arguments to methods on interface primitives
It will be easier to change the implementation of the service if necessary - Jayce.Hyatt92 commented on June 7th 19 at 16:09

Find more questions by tags Patterns of designingPHP