久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

PHP MVC:數據映射器模式:類設計

PHP MVC: Data Mapper pattern: class design(PHP MVC:數據映射器模式:類設計)
本文介紹了PHP MVC:數據映射器模式:類設計的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我有一個帶有域對象和數據映射器的 Web MVC 應用程序.數據映射器的類方法包含所有數據庫查詢邏輯.我試圖避免鏡像任何數據庫結構,因此,在構造 sql 語句時實現最大的靈活性.所以,原則上,我盡量不使用任何 ORM 或 ActiveRecord 結構/模式.

I have a web MVC application with domain objects and data mappers. The class methods of the data mappers contain all database querying logic. I'm trying to avoid mirroring any database structure and, therefore, to achieve the maximum flexibility in constructing the sql statements. So, in principle, I'm trying to not make use of any ORM or ActiveRecord structure/pattern AT ALL.

我舉個例子:通常,我可以有一個抽象類 AbstractDataMapper 被所有特定的數據映射器類繼承——比如 UserDataMapper 類.然后我可以在 AbstractDataMapper 中定義一個 findById() 方法,以獲取特定表的記錄 - 如 users - 通過給定的 id 值,例如用戶身份.但這意味著我總是從單個表中獲取記錄,而無法使用任何左連接來從與給定 id - 用戶 ID 對應的其他一些表中獲取一些其他詳細信息.

Let me give you an example: Normally, I could have an abstract class AbstractDataMapper inherited by all specific data mapper classes - like the UserDataMapper class. And then I could define a findById() method in AbstractDataMapper, to fetch a record of a specific table - like users - by a given id value, e.g. user id. But this would imply that I'd always fetch a record from a single table, without the possibility to use any left joins to also fetch some other details from some other tables corresponding to the given id - user id.

所以,我的問題是:在這些條件下 - 我自己必須要實現一個抽象數據映射器類,還是每個數據映射器類都應該包含它自己完全專有"的數據訪問層實現?

So, my question is: Under these conditions - to which I myself obliged to, should I implement an abstract data mapper class, or each data mapper class should contain its own completely "proprietary" implementation of the data-access layer?

我希望我能清楚地表達我的想法.如果我不清楚或者您有任何問題,請告訴我.

I hope I could express my idea clear. Please tell me, if I was somehow unclear or you have any questions.

非常感謝您的時間和耐心.

Thank you very much for your time and patience.

推薦答案

如果我理解你的意思......

If I understood your point ...

讓所有的具體映射器都從一個公共類繼承 SQL 有幾個你忽略的問題:

Having all your concrete mappers inheriting SQL from a common class has several issues that you have missed:

  • 域對象中的參數名稱取決于列的名稱
  • 有一個獲取方法"在映射器中,沒有相應的表
  • 您還有配置(表名),這是超類所期望的
  • 數據庫架構必須將 id 作為所有 PRIMARY KEY 列的名稱
  • parameter names in your domain objects depend on the names of columns
  • there is a "fetching method" in mappers, that don't have a corresponding table
  • you still have configuration (table name), that is expected by superclass
  • the DB schema must have id as name for all of your PRIMARY KEY columns

現在,我將嘗試打開其中的每一個.

Now, I'm gonna try to unpack each of those.

要創建共享的 findById() 方法,唯一實用的方法是圍繞以下內容構建它:

To create a shared findById() method, the only pragmatic approach is to build it around something like this:

"SELECT * FROM {$this->tableName} WHERE id = :id"

主要問題實際上是通配符 * 符號.

The main issue actually is the wildcard * symbol.

使用數據映射器填充實體有兩種主要方法:使用設置器或使用反射.在這兩種情況下,名稱"都是參數/設置器的數量由您選擇的列隱含.

There are two major approaches for populating an entity using a data mapper: use setters or use reflection. In both cases the "names" of a parameters/setters is implied by columns, that you have selected.

在普通查詢中,您可以執行諸如SELECT name AS fullName FROM ... 之類的操作,這使您可以使用查詢來重新命名 字段.但是對于統一方法",沒有好的選擇.

In a normal query you can do something like SELECT name AS fullName FROM ..., which lets you to use the query for re-naming the fields. But with a "unified approach", there are no good options.

所以,事情是,除非你有一個每個表的映射器結構(在這種情況下,活動記錄開始看起來像務實的選項),你最終會得到很少(非常常見的)邊緣情況".映射器的場景:

So, the thing is, unless you have a mapper-per-table structure (in which case an active record starts look like pragmatic option), you will end up with few (really common) "edge case" scenarios for your mappers:

  • 僅用于保存數據
  • 處理集合而不是單一實體
  • 聚合來自多個表的數據
  • 使用具有復合鍵的表
  • 它實際上不是一個表,而是一個 SQL 視圖
  • ... 或以上的組合

您最初的想法在小規模項目中效果很好(一兩個映射器是邊緣情況").但是對于大型項目,findById() 的使用將是例外而不是常態.

Your original idea would work just fine in a small scale project (with one or two mappers being an "edge case"). But with a large project, the usage of findById() will be the exception not the norm.

要在超類中實際獲得這個 findById() 方法,您需要一種將表名傳達給它的方法.這意味著,您的類定義中有類似 protected $tableName 的內容.

To actually get this findById() method in the superclass, you will need a way to communicate the table name to it. Which would mean, that you have something like protected $tableName in you class definition.

您可以通過在抽象映射器類中使用 abstract function getTableName() 來緩解它,該類在實現時會返回一個全局常量值.

You can mitigate it by having abstract function getTableName() in your abstract mapper class, which, when implemented, returns a value of global constant.

但是,當您的映射器需要處理多個表時會發生什么.

But what happens, when your mapper need to work with multiple tables.

對我來說這似乎是一種代碼味道,因為信息實際上跨越了兩個邊界(因為沒有更好的詞).當此代碼中斷時,超類中的 SQL 將顯示錯誤,這不是錯誤的來源(特別是如果您使用常量).

It seems like a code smell to me, because information actually crosses two boundaries (for lack of better word). When this code breaks, the error will be shown for SQL in the superclass, which isn't where the error originated from (especially, if you go with constants).

這個觀點有點爭議:)

據我所知,調用所有主列 id 的做法來自各種 ORM.這招致的懲罰僅適用于可讀性(和代碼維護).考慮這兩個查詢:

As far as I can tell, the practice of calling all primary columns id comes from various ORMs. The penalty, that this incurs, applies only to readability (and code maintenance). Consider these two queries:

SELECT ar.id, ac.id 
  FROM Articles AS ar LEFT JOIN 
       Accounts AS ac ON ac.id = ar.account_id 
 WHERE ar.status = 'published'

SELECT ar.article_id, ac.account_id 
  FROM Articles AS ar LEFT JOIN 
       Accounts AS ac USING(account_id)
 WHERE ar.status = 'published'

隨著數據庫架構的增長和查詢變得越來越復雜,實際跟蹤id"是什么變得越來越難.代表什么情況.

As the DB schema grows and the queries become more complex, it gets harder and harder to actually keep track of, what the "id" stands for in what case.

我的建議是嘗試為列使用相同的名稱,當它是主鍵和外鍵時(如果可能,因為在某些情況下,例如對于閉包表,它是不可行的").基本上,所有存儲相同類型 ID 的列都應該具有相同的名稱.

My recommendation would be to try same name for column, when it is a primary as when it is a foreign key (when possible, because in some cases, like for "closure tables, it's not viable). Basically, all columns that store IDs of same type, should have the same name.

作為小獎勵,您可以獲得 USING() 語法糖.

As a minor bonus, you get the USING() syntax sugar.

壞主意.你基本上打破了LSP.

Bad idea. You are basically breaking LSP.

這篇關于PHP MVC:數據映射器模式:類設計的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

Action View Helper in Zend - Work around?(Zend 中的動作視圖助手 - 解決方法?)
Is this a good way to match URI to class/method in PHP for MVC(這是將 URI 與 PHP 中用于 MVC 的類/方法匹配的好方法嗎)
Where do I save partial (views) in Zend Framework, to be accessible for all Views in my App?(我在哪里保存 Zend Framework 中的部分(視圖),以便我的應用程序中的所有視圖都可以訪問?) - IT屋-程序員軟件開發技術
Having a single entry point to a website. Bad? Good? Non-issue?(有一個網站的單一入口點.壞的?好的?沒問題?)
Is MVC + Service Layer common in zend or PHP?(MVC + 服務層在 Zend 或 PHP 中常見嗎?)
Hello World example in MVC approach to PHP(PHP MVC 方法中的 Hello World 示例)
主站蜘蛛池模板: 成人免费在线视频 | 成人精品国产免费网站 | 久久高清国产视频 | 精品欧美一区二区精品久久久 | 成人精品一区二区三区中文字幕 | 91久久精品国产免费一区 | 国产成人一区二区三区 | 黄色大全免费看 | 中文字幕日韩欧美 | 一区二区三区在线免费观看视频 | 欧美一区精品 | 中文精品视频 | 日韩在线视频免费观看 | 黄色毛片免费视频 | 9久久精品| 一级片毛片 | 欧美videosex性极品hd | 天天干精品 | 国产乱码精品1区2区3区 | 国产欧美久久精品 | 亚洲国产片 | 日韩欧美在线不卡 | 亚洲一区二区久久久 | 日日噜噜噜夜夜爽爽狠狠视频97 | 日本久久久久久 | 精品欧美色视频网站在线观看 | 日韩中文字幕网 | 日本免费在线看 | 亚洲a视频| 国产第一页在线观看 | 热re99久久精品国99热观看 | 亚洲狠狠丁香婷婷综合久久久 | 午夜精品影院 | 国产精品久久久久久久久久久久久久 | 午夜精品久久久久久久久久久久久 | 91精品久久久久久久久中文字幕 | 色婷婷综合久久久中字幕精品久久 | 成年免费大片黄在线观看岛国 | 国产高潮好爽受不了了夜夜做 | 亚洲黄色av | 色眯眯视频在线观看 |