


Mengendalikan koleksi akar agregat - corak repositori
mata teras
- Model pergudangan dalam reka bentuk yang didorong domain (DDD) bertindak sebagai perantara antara model domain dan lapisan pemetaan data, meningkatkan pengurusan pertanyaan data dan meminimumkan pertindihan.
- Gudang abstrak Kompleksitas lapisan data dari model domain, mempromosikan pemisahan yang jelas tentang kebimbangan dan kejahilan kegigihan, yang selaras dengan prinsip DDD.
- Melaksanakan pergudangan melibatkan encapsulating logik akses data dan operasi di belakang antara muka seperti koleksi, yang dapat memudahkan interaksi dengan model domain.
- Walaupun pergudangan memberikan manfaat yang signifikan dalam kerumitan domain pengurusan dan logik domain pengasingan dan butiran ketekunan data, pelaksanaannya boleh menjadi terlalu kompleks untuk aplikasi mudah.
- Penggunaan praktikal pergudangan boleh diperhatikan dalam sistem yang memerlukan pertanyaan kompleks dan operasi data, di mana mereka menyediakan bahasa yang lebih domain dan mengurangkan kebocoran infrastruktur ke dalam model domain. Salah satu aspek yang paling tipikal dari seni bina reka bentuk domain tradisional (DDD) adalah agnostisitas kegigihan mandatori yang ditunjukkan oleh model domain. Dalam reka bentuk yang lebih konservatif, termasuk beberapa pelaksanaan berdasarkan rekod aktif atau gerbang jadual data (dalam mengejar kesederhanaan yang agak menipu, sering berakhir dengan logik pencemaran infrastruktur), selalu ada konsep yang jelas tentang mekanisme penyimpanan yang mendasari, biasanya pangkalan data relasi. Sebaliknya, model domain direka bentuk secara konseptual dari awal ke alam semula jadi "agnostik" yang ketat, dengan itu mengalihkan mana -mana logik kegigihannya di luar sempadannya. Walaupun mempertimbangkan bahawa DDD agak sukar difahami apabila merujuk kepada "pangkalan data" secara langsung, di dunia nyata, kemungkinan bahawa sekurang -kurangnya satu pangkalan data berjalan di belakang tabir, kerana model domain akhirnya harus berterusan dalam beberapa bentuk. Oleh itu, adalah perkara biasa untuk menggunakan lapisan pemetaan antara model dan lapisan akses data. Ini bukan sahaja secara aktif menggalakkan mengekalkan tahap pengasingan antara lapisan, tetapi juga melindungi setiap detail kompleks dalam kod klien yang melibatkan objek domain bergerak ke belakang antara jurang dalam lapisan masalah. mea culpa
Melakukan persediaan awal
<?php namespace Model; interface UserInterface { public function setId($id); public function getId(); public function setName($name); public function getName(); public function setEmail($email); public function getEmail(); public function setRole($role); public function getRole(); }
<?php namespace Model; class User implements UserInterface { const ADMINISTRATOR_ROLE = "Administrator"; const GUEST_ROLE = "Guest"; protected $id; protected $name; protected $email; protected $role; public function __construct($name, $email, $role = self::GUEST_ROLE) { $this->setName($name); $this->setEmail($email); $this->setRole($role); } public function setId($id) { if ($this->id !== null) { throw new BadMethodCallException( "The ID for this user has been set already."); } if (!is_int($id) || $id throw new InvalidArgumentException( "The user ID is invalid."); } $this->id = $id; return $this; } public function getId() { return $this->id; } public function setName($name) { if (strlen($name) 30) { throw new InvalidArgumentException( "The user name is invalid."); } $this->name = htmlspecialchars(trim($name), ENT_QUOTES); return $this; } public function getName() { return $this->name; } public function setEmail($email) { if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { throw new InvalidArgumentException( "The user email is invalid."); } $this->email = $email; return $this; } public function getEmail() { return $this->email; } public function setRole($role) { if ($role !== self::ADMINISTRATOR_ROLE && $role !== self::GUEST_ROLE) { throw new InvalidArgumentException( "The user role is invalid."); } $this->role = $role; return $this; } public function getRole() { return $this->role; } }
<?php namespace ModelCollection; use MapperUserCollectionInterface, ModelUserInterface; class UserCollection implements UserCollectionInterface { protected $users = array(); public function add(UserInterface $user) { $this->offsetSet($user); } public function remove(UserInterface $user) { $this->offsetUnset($user); } public function get($key) { return $this->offsetGet($key); } public function exists($key) { return $this->offsetExists($key); } public function clear() { $this->users = array(); } public function toArray() { return $this->users; } public function count() { return count($this->users); } public function offsetSet($key, $value) { if (!$value instanceof UserInterface) { throw new InvalidArgumentException( "Could not add the user to the collection."); } if (!isset($key)) { $this->users[] = $value; } else { $this->users[$key] = $value; } } public function offsetUnset($key) { if ($key instanceof UserInterface) { $this->users = array_filter($this->users, function ($v) use ($key) { return $v !== $key; }); } else if (isset($this->users[$key])) { unset($this->users[$key]); } } public function offsetGet($key) { if (isset($this->users[$key])) { return $this->users[$key]; } } public function offsetExists($key) { return ($key instanceof UserInterface) ? array_search($key, $this->users) : isset($this->users[$key]); } public function getIterator() { return new ArrayIterator($this->users); } }
<?php namespace Model; interface UserInterface { public function setId($id); public function getId(); public function setName($name); public function getName(); public function setEmail($email); public function getEmail(); public function setRole($role); public function getRole(); }
<?php namespace Model; class User implements UserInterface { const ADMINISTRATOR_ROLE = "Administrator"; const GUEST_ROLE = "Guest"; protected $id; protected $name; protected $email; protected $role; public function __construct($name, $email, $role = self::GUEST_ROLE) { $this->setName($name); $this->setEmail($email); $this->setRole($role); } public function setId($id) { if ($this->id !== null) { throw new BadMethodCallException( "The ID for this user has been set already."); } if (!is_int($id) || $id throw new InvalidArgumentException( "The user ID is invalid."); } $this->id = $id; return $this; } public function getId() { return $this->id; } public function setName($name) { if (strlen($name) 30) { throw new InvalidArgumentException( "The user name is invalid."); } $this->name = htmlspecialchars(trim($name), ENT_QUOTES); return $this; } public function getName() { return $this->name; } public function setEmail($email) { if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { throw new InvalidArgumentException( "The user email is invalid."); } $this->email = $email; return $this; } public function getEmail() { return $this->email; } public function setRole($role) { if ($role !== self::ADMINISTRATOR_ROLE && $role !== self::GUEST_ROLE) { throw new InvalidArgumentException( "The user role is invalid."); } $this->role = $role; return $this; } public function getRole() { return $this->role; } }
Unbox, kumpulan tugas yang dilakukan oleh Usermapper agak mudah, terhad untuk mendedahkan beberapa pencari umum yang bertanggungjawab untuk mengekstrak pengguna dari pangkalan data dan membina semula entiti yang sepadan melalui kaedah CreateUser (). Juga, jika anda telah menyelidiki beberapa pemetaan sebelum ini, dan juga menulis karya pemetaan anda sendiri, di atas pastinya mudah difahami. Satu -satunya perincian halus yang menyoroti mungkin bahawa UserCollectionInterface telah diletakkan di lapisan pemetaan, bukan dalam model. Saya melakukan ini dengan tujuan kerana dengan cara ini, abstraksi (protokol) yang koleksi pengguna bergantung secara eksplisit diisytiharkan dan dimiliki oleh usermapper peringkat yang lebih tinggi, yang konsisten dengan panduan yang dipromosikan oleh prinsip penyongsangan ketergantungan. Dengan pemetaan yang telah ditubuhkan, kami boleh menggunakannya secara langsung dari kotak dan mengeluarkan beberapa objek pengguna dari storan untuk membolehkan model menghidrat dengan segera. Walaupun ini seolah -olah menjadi jalan yang betul pada pandangan pertama, kita sebenarnya mencemarkan logik aplikasi dengan infrastruktur yang tidak perlu kerana pemetaan sebenarnya adalah sebahagian daripada infrastruktur. Bagaimana jika pada masa akan datang, perlu untuk menanyakan entiti pengguna berdasarkan keadaan yang lebih terperinci, khusus domain (bukan hanya keadaan biasa yang didedahkan oleh pencari mapper)? Dalam kes ini, ia perlu meletakkan lapisan tambahan di atas lapisan pemetaan, yang bukan sahaja menyediakan tahap akses data yang lebih tinggi, tetapi juga membawa blok logik pertanyaan melalui satu titik. Akhirnya, itulah jumlah manfaat yang kami harapkan dari pergudangan.
Melaksanakan pergudangan pengguna
Dalam persekitaran pengeluaran, pergudangan dapat melaksanakan hampir semua yang dapat difikirkan di permukaannya untuk mendedahkan ilusi set memori akar agregat kepada model. Walau bagaimanapun, dalam kes ini, kita tidak boleh mengharapkan untuk menikmati kemewahan mahal ini secara percuma, kerana gudang yang akan kita bina akan menjadi struktur yang agak buatan yang bertanggungjawab untuk mengekstrak pengguna dari pangkalan data:
<?php namespace ModelCollection; use MapperUserCollectionInterface, ModelUserInterface; class UserCollection implements UserCollectionInterface { protected $users = array(); public function add(UserInterface $user) { $this->offsetSet($user); } public function remove(UserInterface $user) { $this->offsetUnset($user); } public function get($key) { return $this->offsetGet($key); } public function exists($key) { return $this->offsetExists($key); } public function clear() { $this->users = array(); } public function toArray() { return $this->users; } public function count() { return count($this->users); } public function offsetSet($key, $value) { if (!$value instanceof UserInterface) { throw new InvalidArgumentException( "Could not add the user to the collection."); } if (!isset($key)) { $this->users[] = $value; } else { $this->users[$key] = $value; } } public function offsetUnset($key) { if ($key instanceof UserInterface) { $this->users = array_filter($this->users, function ($v) use ($key) { return $v !== $key; }); } else if (isset($this->users[$key])) { unset($this->users[$key]); } } public function offsetGet($key) { if (isset($this->users[$key])) { return $this->users[$key]; } } public function offsetExists($key) { return ($key instanceof UserInterface) ? array_search($key, $this->users) : isset($this->users[$key]); } public function getIterator() { return new ArrayIterator($this->users); } }
<?php namespace Mapper; use ModelUserInterface; interface UserCollectionInterface extends Countable, ArrayAccess, IteratorAggregate { public function add(UserInterface $user); public function remove(UserInterface $user); public function get($key); public function exists($key); public function clear(); public function toArray(); }
<?php namespace Mapper; use ModelRepositoryUserMapperInterface, ModelUser; class UserMapper implements UserMapperInterface { protected $entityTable = "users"; protected $collection; public function __construct(DatabaseAdapterInterface $adapter, UserCollectionInterface $collection) { $this->adapter = $adapter; $this->collection = $collection; } public function fetchById($id) { $this->adapter->select($this->entityTable, array("id" => $id)); if (!$row = $this->adapter->fetch()) { return null; } return $this->createUser($row); } public function fetchAll(array $conditions = array()) { $this->adapter->select($this->entityTable, $conditions); $rows = $this->adapter->fetchAll(); return $this->createUserCollection($rows); } protected function createUser(array $row) { $user = new User($row["name"], $row["email"], $row["role"]); $user->setId($row["id"]); return $user; } protected function createUserCollection(array $rows) { $this->collection->clear(); if ($rows) { foreach ($rows as $row) { $this->collection[] = $this->createUser($row); } } return $this->collection; } }
Walaupun di atas struktur yang agak ringan, pelaksanaan userrepository sangat intuitif kerana APInya membolehkannya mengekstrak koleksi objek pengguna dari storan yang mematuhi predikat halus yang berkait rapat dengan bahasa model. Di samping itu, dalam keadaan semasa, repositori hanya mendedahkan beberapa pencari mudah kepada kod klien, yang seterusnya menggunakan fungsi pemetaan data untuk mengakses storan. Dalam persekitaran yang lebih realistik, pergudangan juga harus dapat meneruskan akar agregat. Jika anda ingin menambah kaedah sisipan () atau kaedah lain yang serupa untuk userrepository, jangan ragu untuk berbuat demikian. Dalam kedua -dua kes, cara yang berkesan untuk menangkap kelebihan sebenar menggunakan pergudangan melalui contoh adalah:
<?php namespace Model; interface UserInterface { public function setId($id); public function getId(); public function setName($name); public function getName(); public function setEmail($email); public function getEmail(); public function setRole($role); public function getRole(); }
Seperti yang disebutkan sebelumnya, pergudangan secara berkesan menukar istilah perniagaan dengan kod klien (yang disebut "bahasa sejagat" yang dicipta oleh Eric Evans dalam bukunya "Reka Bentuk Domain Domain") dan bukannya istilah teknikal peringkat rendah. Tidak seperti kekaburan yang terdapat dalam Finder Mapper Data, sebaliknya, kaedah pergudangan menggambarkan dirinya dengan "nama", "e -mel", dan "peranan", yang tidak diragukan lagi sebahagian daripada sifat entiti pengguna pemodelan. Pengekstrakan data peringkat yang lebih tinggi, dan satu set lengkap yang diperlukan apabila merangkumi logik pertanyaan dalam sistem kompleks adalah salah satu sebab yang paling menarik mengapa pergudangan lebih menarik dalam reka bentuk pelbagai lapisan. Sudah tentu, kebanyakan masa, terdapat perdagangan yang tersirat di antara kerumitan untuk mendapatkan manfaat ini di hadapan dan menggunakan lapisan abstraksi tambahan (yang boleh terlalu kembung dalam aplikasi yang lebih mudah).
Kesimpulan
Sebagai salah satu konsep teras dalam reka bentuk yang didorong oleh domain, pergudangan boleh didapati dalam aplikasi yang ditulis dalam beberapa bahasa lain seperti Java dan C#, untuk menamakan beberapa. Walau bagaimanapun, dalam PHP, mereka masih tidak diketahui, hanya mengambil langkah pertama di dunia. Namun, terdapat beberapa rangka kerja yang dipercayai seperti Flow3 dan tentu saja doktrin 2.x yang dapat membantu anda mengamalkan paradigma DDD. Seperti mana -mana pendekatan pembangunan yang sedia ada, anda tidak perlu menggunakan repositori dalam permohonan anda, atau bahkan tidak perlu menghancurkannya dengan timbunan konsep di belakang DDD. Hanya gunakan akal dan pilih mereka hanya jika anda fikir ia sesuai untuk keperluan anda. Itu mudah. Gambar dari Chance Agrella / Freeheerestock.com
Soalan Lazim Mengenai Pengendalian Koleksi Root Agregat (Soalan Lazim)
Dalam reka bentuk yang didorong domain (DDD), akar agregat adalah koleksi objek yang berkaitan yang dianggap sebagai unit. Objek ini terikat bersama oleh entiti akar (juga dikenali sebagai akar agregat). Akar agregasi mengekalkan konsistensi perubahan yang dibuat kepada agregasi dengan melarang objek luaran untuk memegang rujukan kepada ahli -ahlinya.
Bagaimana perbezaan antara akar agregat dan entiti biasa?
Perbezaan utama antara akar agregat dan entiti biasa adalah tanggungjawab mereka. Entiti biasa merangkumi tingkah laku dan keadaan, sementara akar agregasi juga memastikan integriti keseluruhan agregasi dengan mengawal akses kepada anggotanya. Ia adalah satu -satunya ahli dalam pengagregatan yang membolehkan objek luaran memegang rujukan kepada mereka.
Bagaimana mengenal pasti akar agregat dalam model domain saya?
Mengenal pasti akar agregasi memerlukan pemahaman yang mendalam tentang kawasan perniagaan. Ia biasanya merupakan entiti peringkat tinggi dengan identiti global dan merangkumi entiti lain dan objek nilai. Sebagai contoh, dalam dunia e-dagang, pesanan boleh menjadi akar agregat yang merangkumi item baris dan maklumat penghantaran.
Bagaimana menangani koleksi akar agregat?
Memproses koleksi akar agregat boleh mencabar. Adalah penting untuk diingat bahawa setiap akar agregat adalah sempadan konsistensi, jadi perubahan kepada satu akar agregat tidak boleh menjejaskan akar agregat lain. Oleh itu, apabila memproses koleksi, biasanya lebih baik untuk memuat dan berterusan setiap akar agregat secara berasingan untuk konsistensi.
Bolehkah akar agregat merujuk kepada akar agregat yang lain?
Ya, akar agregat boleh merujuk kepada akar agregat yang lain, tetapi ia harus dirujuk hanya dengan pengenalan. Ini bermakna ia tidak boleh memegang rujukan langsung kepada objek akar agregat yang lain, tetapi IDnya. Ini membantu mengekalkan sempadan konsistensi untuk setiap akar agregat.
Bagaimanakah akar agregat berkaitan dengan pergudangan dalam DDD?
Dalam DDD, pergudangan menyediakan kaedah untuk mendapatkan dan menyimpan akar agregat. Ia menafsirkan mekanisme penyimpanan yang mendasari, yang membolehkan model domain mengabaikan butiran ketekunan data. Setiap akar agregat biasanya mempunyai storan sendiri.
Apakah peranan akar agregasi dalam melaksanakan peraturan perniagaan?
Akar agregasi memainkan peranan penting dalam melaksanakan peraturan perniagaan. Ia memastikan bahawa semua perubahan kepada agregasi meletakkannya dalam keadaan yang sah. Ini bermakna mana -mana peraturan perniagaan yang merangkumi pelbagai entiti atau objek nilai hendaklah dikuatkuasakan oleh akar agregat.
Bagaimana root agregasi membantu mengurangkan kerumitan dalam model domain?
Akar agregasi membantu mengurangkan kerumitan dalam model domain dengan bertindak sebagai sempadan konsistensi dan mengawal akses kepada ahli mereka. Ia memudahkan model dengan menyediakan satu titik interaksi untuk setiap pengagregatan, menjadikannya lebih mudah untuk memahami sistem.
Bolehkah akar agregat menjadi sebahagian daripada pelbagai agregat?
Tidak, akar agregat tidak boleh menjadi sebahagian daripada pelbagai agregat. Ini akan melanggar sempadan konsistensi agregat dan boleh menyebabkan ketidakkonsistenan dalam model domain.
Bagaimana menangani masalah konkurensi akar agregat?
Pelbagai strategi boleh digunakan untuk menangani masalah konkurensi pada akar agregat, seperti kunci optimis atau kunci pesimis. Pilihan dasar bergantung kepada keperluan khusus permohonan dan sifat masalah keseragaman yang anda hadapi.
Output yang disemak semula ini mengekalkan pemformatan imej asal dan lokasi, memaklumkan teks untuk mengelakkan plagiarisme, dan menyimpan makna teras utuh.
Atas ialah kandungan terperinci Mengendalikan koleksi akar agregat - corak repositori. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Alipay Php ...

JWT adalah standard terbuka berdasarkan JSON, yang digunakan untuk menghantar maklumat secara selamat antara pihak, terutamanya untuk pengesahan identiti dan pertukaran maklumat. 1. JWT terdiri daripada tiga bahagian: header, muatan dan tandatangan. 2. Prinsip kerja JWT termasuk tiga langkah: menjana JWT, mengesahkan JWT dan muatan parsing. 3. Apabila menggunakan JWT untuk pengesahan di PHP, JWT boleh dijana dan disahkan, dan peranan pengguna dan maklumat kebenaran boleh dimasukkan dalam penggunaan lanjutan. 4. Kesilapan umum termasuk kegagalan pengesahan tandatangan, tamat tempoh, dan muatan besar. Kemahiran penyahpepijatan termasuk menggunakan alat debugging dan pembalakan. 5. Pengoptimuman prestasi dan amalan terbaik termasuk menggunakan algoritma tandatangan yang sesuai, menetapkan tempoh kesahihan dengan munasabah,

Sesi rampasan boleh dicapai melalui langkah -langkah berikut: 1. Dapatkan ID Sesi, 2. Gunakan ID Sesi, 3. Simpan sesi aktif. Kaedah untuk mengelakkan rampasan sesi dalam PHP termasuk: 1. Gunakan fungsi Sesi_Regenerate_ID () untuk menjana semula ID Sesi, 2. Data sesi stor melalui pangkalan data, 3.

Penerapan prinsip pepejal dalam pembangunan PHP termasuk: 1. Prinsip Tanggungjawab Tunggal (SRP): Setiap kelas bertanggungjawab untuk hanya satu fungsi. 2. Prinsip Terbuka dan Tutup (OCP): Perubahan dicapai melalui lanjutan dan bukannya pengubahsuaian. 3. Prinsip Penggantian Lisch (LSP): Subkelas boleh menggantikan kelas asas tanpa menjejaskan ketepatan program. 4. Prinsip Pengasingan Antara Muka (ISP): Gunakan antara muka halus untuk mengelakkan kebergantungan dan kaedah yang tidak digunakan. 5. Prinsip Inversi Ketergantungan (DIP): Modul peringkat tinggi dan rendah bergantung kepada abstraksi dan dilaksanakan melalui suntikan ketergantungan.

Bagaimana cara debug mod CLI dalam phpstorm? Semasa membangun dengan PHPStorm, kadang -kadang kita perlu debug PHP dalam mod Interface Line Command (CLI) ...

Bagaimana untuk menetapkan keizinan UnixSocket secara automatik selepas sistem dimulakan semula. Setiap kali sistem dimulakan semula, kita perlu melaksanakan perintah berikut untuk mengubahsuai keizinan UnixSocket: sudo ...

Mengikat statik (statik: :) Melaksanakan pengikatan statik lewat (LSB) dalam PHP, yang membolehkan kelas panggilan dirujuk dalam konteks statik dan bukannya menentukan kelas. 1) Proses parsing dilakukan pada masa runtime, 2) Cari kelas panggilan dalam hubungan warisan, 3) ia boleh membawa overhead prestasi.

Menghantar data JSON menggunakan perpustakaan Curl PHP dalam pembangunan PHP, sering kali perlu berinteraksi dengan API luaran. Salah satu cara biasa ialah menggunakan perpustakaan curl untuk menghantar post ...
