ORM: Data Mapper เทียบกับ Active Record
ORM ย่อมาจากObject-Relational Mappingนั่นคือเทคนิคที่แปลง Object จาก OOP เป็นแถวในฐานข้อมูลและในทางกลับกัน
มีสองรูปแบบ:
- บันทึกที่ใช้งานอยู่ : บันทึก (เอนทิตี) เองสามารถเปลี่ยนฐานข้อมูลได้
- Data Mapper : มีวัตถุภายนอกที่คงอยู่ในเอนทิตี
บันทึกที่ใช้งานอยู่
ดังที่ฉันได้กล่าวไว้ก่อนหน้านี้ เอนทิตีนั้นสามารถสร้าง อัปเดต หรือลบได้ ตัวอย่างเช่น ใน PHP Eloquent เป็น Active Record ORM ที่พัฒนาโดยชุมชน 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
}
}
ใน data mapper เราต้องการคลาสภายนอกที่จะอัพเดต DB ใน PHP ตัวอย่างเช่น Doctrine คือ Data Mapper ORM สำหรับ 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();
}
}
แม้ว่าหากคุณดูที่ส่วนย่อยทั้งสอง คุณจะเห็นว่า Data Mapper กำลังใช้การพึ่งพาภายนอก ( Entity Managerวัตถุ ) ซึ่งแปลกและชัดเจน แต่ยากขึ้นหากคุณตัดสินใจที่จะแนะนำการทดสอบบางอย่างในชั้นUserCreatorเรียน ในขณะเดียวกันในActive Recordชั้นเรียน เอนทิตีกำลังช่วยตัวเอง ดังนั้นเราจึงไม่มีการพึ่งพาใด ๆ ในทันที แต่นั่นไม่เป็นความจริงทั้งหมด เอนทิตีเองก็มีความรู้เกี่ยวกับฐานข้อมูล และจะเป็นการยากที่จะเขียนการทดสอบบางอย่างหากเราใช้เอนทิตีUserโดยตรง
รูปแบบที่เก็บข้อมูล
รูปแบบพื้นที่เก็บข้อมูลเป็นรูปแบบการออกแบบที่ซ่อนตรรกะของฐานข้อมูลไว้ในคลาสใหม่ โดยเปิดเผยเฉพาะวิธีการที่เราต้องการให้กับผู้ใช้
ในการทำเช่นนี้ เราจำเป็นต้องสร้างอินเทอร์เฟซและคลาสที่จะใช้อินเทอร์เฟซซึ่งเราจะทิ้งลอจิกทั้งหมด
# 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);
}
}





































![รายการที่เชื่อมโยงคืออะไร? [ส่วนที่ 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)