ORM: Data Mapper vs Active Record
ORM oznacza Object-Relational Mapping , czyli technikę, która przekształca obiekty z OOP w wiersze w bazie danych i odwrotnie.
Istnieją dwa wzory:
- Rekord aktywny : Sam rekord (jednostka) może aktywnie zmieniać bazę danych
- Data Mapper : Istnieje obiekt zewnętrzny, który utrwala jednostki
Aktywny rekord
Jak wcześniej wspomniałem, sam podmiot można tworzyć, aktualizować lub usuwać. Na przykład w PHP Eloquent to Active Record ORM opracowany przez społeczność Laravel.
final class UserCreator
{
public function create(UserInformation $userInfo): void
{
$address = Address::createFrom($userInfo->address());
$address->save() # Address is stored in the database
$user = User::createFrom($userInfo->user());
$user->address = $address; // Set relationship
$user->save(); # User is stored in the database
}
}
W mapowaniu danych potrzebujemy zewnętrznej klasy, która zaktualizuje bazę danych. Na przykład w PHP Doctrine jest de facto Data Mapper ORM dla Symfony.
final class UserCreator
{
public function __construct(
private EntityManager $entityManager,
) {}
public function create(UserInformation $userInfo): void
{
$address = Address::createFrom($userInfo->address());
$user = User::createFrom($userInfo->user());
$user->address = $address; # Set relationship
# We persist all objects we want to update
$this->entityManager->persist($address);
$this->entityManager->persist($user);
# Finally, flushing the entity manager will execute the SQLs
$this->entityManager->flush();
}
}
Chociaż, jeśli spojrzysz na oba fragmenty, możesz już zobaczyć, że Data Mapper używa zewnętrznej zależności ( Entity Managerobiektu), która jest dziwna i wyraźnie, jest trudniej, jeśli zdecydujesz się wprowadzić kilka testów do klasy UserCreator, tymczasem w Active Recordklasie, encje same się ratują, więc na pierwszy rzut oka nie mamy żadnej zależności, ale to nie do końca prawda, encja sama ma wiedzę o DB i ciężko będzie napisać jakieś testy, jeśli użyjemy encji bezpośrednio User.
Wzór repozytorium
Wzorzec repozytorium to wzorzec projektowy, który ukrywa logikę bazy danych w nowej klasie, ujawniając tylko metody, które chcemy udostępnić użytkownikowi.
Aby to zrobić, musimy stworzyć interfejs i klasę, która zaimplementuje interfejs, w którym usuniemy całą logikę.
# App/User/Domain
interface UserRepository
{
public function save(UserInformation $userInfo): void;
}
~~~~
# App/User/Infrastructure
final class ActiveRecordUserRepository implements UserRepository
{
public function save(UserInformation $userInfo): void
{
$address = Address::createFrom($userInfo->address());
$address->save()
$user = User::createFrom($userInfo->user());
$user->address = $address;
$user->save();
}
}
final class DataMapperUserRepository implements UserRepository
{
public function __construct(
private EntityManager $entityManager,
) {}
public function create(UserInformation $userInfo): void
{
$address = Address::createFrom($userInfo->address());
$user = User::createFrom($userInfo->user());
$user->address = $address;
$this->entityManager->persist($address);
$this->entityManager->persist($user);
$this->entityManager->flush();
}
}
final class UserCreator
{
public function __construct(
private UserRepository $userRepository,
) {}
public function create(UserInformation $userInfo): void
{
$this->userRepository->save($userInfo);
}
}

![Czym w ogóle jest lista połączona? [Część 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































