2.4. Data Mapper¶
2.4.1. تعریف¶
دیزاین پترن Data Mapper یک الگوی طراحیست که کار آن جداسازی منطق برنامه از لایه های سطح پایین برنامه مربوط به ذخیره سازی و کار با لایه داده (دیتابیس) هاست.
در واقع این دیزاین پترن یک نگاشت ایجاد می کنه بین آبجکت های برنامه و جدول های پایگاه داده.
فکر کنم اکثرا با ORM کار کرده باشید و این دیزاین پترن رو بشناسید.
2.4.2. چه زمانی استفاده میشه؟¶
این الگو تقریبا در تمام فریمورک های مطرح برای جداسازی لایه منطق و بخش کار با سیستم ذخیره سازی مورد استفاده قرار گرفته.
به عنوان مثال الگویی که در پیاده سازی Doctrine استفاده شده Data Mapper هست.
دقت کنید که لایه مدل ها و Eloquent در لاراول از Active Record Pattern استفاده می کنه و این دو الگو با هم فرق دارن.
2.4.3. اجزاء¶
این دیزاین پترن از چند قسمت اصلی تشکیل شده که با هم مرور می کنیم.
بخش اول دیتابیس هست که همون لایه ذخیره سازی برنامه محسوب میشه. همون قسمتی که قراره از منطق برنامه جدا بشه!
بخش بعد Domain Objects هستن که نماینده ی موجودیت های برنامه هستن، موجودیت هایی مثل کاربران، محصولات، سفارشات و…
و در نهایت هم یک نگاشت کننده داده یا Data Mapper داریم که میان این دو قسمت قرار میگیره و کارش هم مشخصه!
Caution
✅ مزایای استفاده
برخلاف Active Record اصل تک مسئولیتی را رعایت می کند
بسیار منعطف هست و امکان گسترش و سفارشی سازی خیلی خوبی به توسعه دهنده میده
جداسازی منطق و سطوح پایین برنامه و رعایت اصل Open/Closed از اصول SOLID
Warning
❌ معایب استفاده
ممکنه کمی انجام setup اون برای توسعه دهنده ها زمان بر باشه
2.4.4. کاربرد عملی¶
خب بریم برای پیاده سازی یک مثال عملی از کلاس User و پیاده سازی Mapper مربوطه.
2.4.5. پیاده سازی¶
قبل از هر چیز کلاس User رو داریم:
1<?php
2
3class User
4{
5 private int $id;
6 private string $name;
7 private string $email;
8
9 public function __construct(int $id, string $name, string $email)
10 {
11 $this->id = $id;
12 $this->name = $name;
13 $this->email = $email;
14 }
15
16 public function getId(): int
17 {
18 return $this->id;
19 }
20
21 public function getName(): string
22 {
23 return $this->name;
24 }
25
26 public function getEmail(): string
27 {
28 return $this->email;
29 }
30
31 public function setId(int $id): void
32 {
33 $this->id = $id;
34 }
35}
و بعد Mapper رو به این صورت تعریف می کنیم:
1<?php
2
3class UserMapper
4{
5 private PDO $db;
6
7 public function __construct($db)
8 {
9 $this->db = $db;
10 }
11
12 public function getById($id): ?User
13 {
14 $stmt = $this->db->prepare('SELECT * FROM users WHERE id = :id');
15 $stmt->bindParam(':id', $id);
16 $stmt->execute();
17 $result = $stmt->fetch(PDO::FETCH_ASSOC);
18
19 if (!$result) {
20 return null;
21 }
22
23 return new User($result['id'], $result['name'], $result['email']);
24 }
25
26 public function save(User $user): void
27 {
28 $stmt = $this->db->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
29 $name = $user->getName();
30 $stmt->bindParam(':name', $name);
31 $email = $user->getEmail();
32 $stmt->bindParam(':email', $email);
33 $stmt->execute();
34 $user->setId($this->db->lastInsertId());
35 }
36}
این Mapper عملیات خواندن و نوشتن رو در پایگاه داده انجام میده.
2.4.6. نحوه فراخوانی¶
1<?php
2
3$db = new PDO('mysql:host=localhost;dbname=mydb', 'username', 'password');
4
5$userMapper = new UserMapper($db);
6$user = $userMapper->getById(1);
7echo $user->getName(); // Outputs the user's name
8
9$newUser = new User(null, 'John Doe', 'john@example.com');
10$userMapper->save($newUser);
11echo $newUser->getId(); // Outputs the new user's ID
فکر کنم نیاز به توضیح نداره و همه چیز کاملا مشخصه!