问题描述
我有一个规范化的数据库,用于存储Internet上文件的位置.一个文件可能具有分布在不同站点上的多个位置.我将URL分两部分存储(Site.UrlStart,FileLocation.UrlEnd). UrlEnd是该文件(对于网站)唯一的部分.
简化的Db结构:
http://img231.imageshack.us/img231/9134/dblayout.jpg
我正在使用 Zend_Db 作为我的ORM(如果是),以及用于从Zend_Db_Table_Abstract继承的表的类.
问题是,检索位置数据(例如url)需要使用多个表,并且据我所知,我要么必须同时使用两个表类(从而公开我的表结构),要么要分散sql遍及我的应用程序,听起来都不吸引人.
我唯一看到的解决方案是创建一个外观类似于Zend_Db_Table_Abstract的外观(也许是继承自它?),并且隐藏了数据实际上在两个表上的事实.
我的问题如下:
- 创建外观类时,我朝着正确的方向走吗(还有其他替代方法吗?)
- facade类是否应该从
Zend_Db_Table_Abstract
继承?
除了非常简单的用例之外,Zend Db Table并不是真正的ORM.它应与系统中的每个表紧密相关.因此,每个表将有一个Zend_Db_Table类.
要管理大局,您将需要另一种类型的课程.
所以,是的,关于使用某种外观,您处于正确的位置.
但是,我不会使其继承自Zend_Db_Table_Abstract,因为它的职责范围非常不同.
可能值得研究一下Data Mapper模式-有点像立面(Martin Fowler,企业体系结构模式).每个域实体类型"都有一个映射器(不一定与每个表相同),对于整个类型族,可能还有另一个额外的映射器.
在Zend Framework的简介页上有一个简单的Data Mapper模式示例: http://framework.zend.com/manual/en/learning .quickstart.create-model.html
请注意Application_Model_GuestbookMapper 如何使用-不扩展Application_Model_DbTable_Guestbook.
但是,这是一个非常简单的示例,有时可能会给您带来比答案更多的问题.
斯科特·安伯勒(Scott Ambler)的另一个学习如何将数据库映射到模型的好资源.
在线文章: http://www.agiledata.org/essays/mappingObjects.html
这涵盖了处理数据到数据与对象到对象以及数据到对象之间的关系的过程: http://www.agiledata.org/essays/mappingObjects.html#MappingRelationships
它也触及了Data Mapper Pattern,并且是为数不多的关于如何将类层次结构映射到db表的很好解释的地方之一.
此外,埃里克·埃文斯(Eric Evans)还描述了存储库"的使用,存储库"是位于模型和数据层之间的立面.如果使用Data Mappers创建成熟的ORM似乎令人生畏,这可能是一个快速的起点.通常,每个重要的域实体(即集合根实体,即一串葡萄串")都具有一个存储库.
查看有关存储库的更多信息: http://books.google.co.uk/books?id=7dlaMs0SECsC&lpg=PP1&dq=Domain-Driven%20Design&pg=PA147#v=onepage&q&f=false
基本上,存储库除其他外,还有一个FindById()类型的方法,这些方法然后可以封装其外观背后的三个Zend Db Table对象的使用.您的模型可以立即开始使用回购".然后,有一天,如果您想添加更多精美的ORM内容,只需将其交换到Repo Facade后面,您的模型甚至不必知道它.
如果这三个表代表拥有独立生活的实体,那么最好有三组类来管理其每个生命周期.如果是这种情况,那么您将使用一种服务"(特别是Eric Evans的模式中的另一种)来管理它们之间的交互.服务是放置似乎不适合任何独占实体的操作的地方.
主要要点是从心理上摆脱Zend Db Table的统治地位-它只是次要角色,是db表的代表而已.
I have a normalized database that stores locations of files on the internet. A file may have multiple locations spread across different sites. I am storing the urls in two parts (Site.UrlStart, FileLocation.UrlEnd). The UrlEnd is the part unique to that file (for the site).
Simplified Db structure:
http://img231.imageshack.us/img231/9134/dblayout.jpg
I am using Zend_Db as my ORM (If it is that), with classes for the tables inheriting from Zend_Db_Table_Abstract.
The issue is that retrieving the location data (e.g. the url) requires the use of multiple tables and as far as I can make out and I would either have to use both table classes (thereby exposing my table structure) or scatter sql all over my application, neither of which sound appealing.
The only solution I can see is to create a façade that acts like Zend_Db_Table_Abstract (Maybe inherits from it?) and hides the fact that the data is actually on two tables.
My questions are as follows:
- Am I going in the right direction in creating a façade class (Are there other alternatives)?
- Should the facade class inherit from
Zend_Db_Table_Abstract
?
Zend Db Table is not really an ORM beyond very simple use cases. It is meant to be closely related to each table in your system. So, you would have one Zend_Db_Table class for each table.
To manage the bigger picture you would need another type of class.
So, yes, you are on the right lines with regards to using a kind-of façade.
However, I would not make it inherit from Zend_Db_Table_Abstract because it has a very different set of responsibilities.
It might be worth looking into the Data Mapper pattern - which is kind-of like a façade (Martin Fowler, Patterns Of Enterprise Architecture). You'd have one Mapper per 'Type of Domain Entity' (which is not necessarily the same as one per table) and maybe another, extra, mapper for a whole family of types.
A simple example of the Data Mapper patterns is on Zend Framework's intro pages:http://framework.zend.com/manual/en/learning.quickstart.create-model.html
Note how Application_Model_GuestbookMapper uses Application_Model_DbTable_Guestbook - and does not extend it.
However that is quite a simple example and can sometimes leave you with lots more questions than answers.
Another good resource for learning about how to map a db to your model is Scott Ambler's
online article: http://www.agiledata.org/essays/mappingObjects.html
That covers the process of dealing with relationships between data-to-data and object-to-object and data-to-object :http://www.agiledata.org/essays/mappingObjects.html#MappingRelationships
It also touches upon the Data Mapper Pattern and is one of the few places where you see a nice explanation of how to map class hierarchies to db tables.
Also Eric Evans has described the use of 'Repositories', which, are facades that sit between your model and the data layer. This could be a quick starting point if making a fully fledged ORM with Data Mappers seems daunting. You'd generally have one Repository per important Domain Entity (i.e Aggregate Root Entities, 'the stalks of bunches of grapes').
See more about repositories:http://books.google.co.uk/books?id=7dlaMs0SECsC&lpg=PP1&dq=Domain-Driven%20Design&pg=PA147#v=onepage&q&f=false
Basically the Repository has, amongst others, a FindById() type methods which then could encapsulate the use of your three Zend Db Table objects behind its façade. Your model can start using the 'Repo' straight away. Then, one day if you want to add more fancy ORM stuff you just swap it behind the Facade of the Repo and your model does not have to even know about it.
If those three tables represent Entity's that lead independent lives, then it might be best to have three sets of classes that manage each of their life-cycles. If this is the case then you would use 'a Service' (specifically another one of Eric Evans' Patterns) to manage their interactions. A service is a place to put operations that do not seem to fit with any one, exclusive Entity.
The main point is to psychologically detach yourself from the dominance of Zend Db Table - it is just a minor player, a representation of the db tables and not much more.
这篇关于使用Zend_Db和多个表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!