我刚开始推动ORM (和总体上的ORM),并试图在MySQL数据库中正确、干净地解决外键关系方面得到一点帮助。
从3个简单的MySQL表开始:
英雄:
技能:
hero_skill:
其中hero_skill具有预期的外键属性,并具有所有Propel类生成。
在推进过程中,我如何完全“水合物”一个“英雄”对象,并以通用的方式引用他们所有的技能--,
关于如何使用特定函数执行此操作的简单示例:
function getAllTheHeroes(){
$query = PropelQuery::from("Hero")
$heroes = $query->find(); //hero model objects
foreach($heroes as $hero){
$heroSkills = $hero->getHeroSkills(); //hero_skill model objects
foreach($heroSkills as $heroSkill){
$skill = $heroSkill->getSkill(); //skill model object.
}
echo $hero->exportTo('JSON'); //export to JSON string (new in Propel 1.6)
}
}
因此,上面的代码获取所有的英雄,迭代和获得所有hero_skill记录的hero_id集合,然后迭代和获取skill_id的技能记录。重要的是,它将所有这些已解析的关系打包为对Hero对象的引用,因此对getWHATEVER()‘水合物’的调用使用了该数据,因此当每个英雄被导出到JSON时,它有一个包含该英雄的所有技能记录的列表,而不仅仅是ids。只要您编写自定义函数来处理每种对象类型,这就可以正常工作了。由此产生的JSON类似于:
[{
"Id":1,
"Name":"Hero McHeroington",
"Description":"Awesome.",
"HeroSkills":
{
"HeroSkill_0":
{
"Id":1,
"HeroId":1,
"SkillId":2,
"Skill":
{
"Id":2,
"Name":"Interpretive Dance",
"Rank":5
}
},
"HeroSkill_1":
{
"Id":2,
"HeroId":1,
"SkillId":4,
"Skill":
{
"Id":4,
"Name":"Pottery",
"Rank":2
}
},
"HeroSkill_2":
{
"Id":3,
"HeroId":1,
"SkillId":5,
"Skill":
{
"Id":5,
"Name":"Walking",
"Rank":1
}
}
}
},{
"Id":2,
"Name":"Squire McTinyPants",
"Description":"Chipper.",
"HeroSkills":
{
"HeroSkill_0":
{
"Id":4,
"HeroId":2,
"SkillId":2,
"Skill":
{
"Id":2,
"Name":"Interpretive Dance",
"Rank":10
}
},
"HeroSkill_1":
{
"Id":5,
"HeroId":2,
"SkillId":3,
"Skill":
{
"Id":3,
"Name":"Peeping",
"Rank":6
}
},
"HeroSkill_2":
{
"Id":6,
"HeroId":2,
"SkillId":6,
"Skill":
{
"Id":6,
"Name":"Skipping",
"Rank":4
}
}
}
}]
诸如此类。
我想做的是一些更普通的事情:
function getModel($byClassName){
$pq = PropelQuery::from($byClassName)
$recs = $pq->find(); // <- collection of records of unknown type
foreach ($recs as $rec){
//Somehow retrieve all of the 'getFOREIGNKEY' Propel generated helper functions and call them all in sequence,
// then iterate down into any of these logical children objects and repeat the process to fully resolve all Foreign Key relationships within this Object
// and all this Objects 'children'
// AND not get stuck in infinite loops due to Many-To-Many relationships from the 'getWHATEVER' calls running in circles.
//Or some other method entirely to accomplish the same thing that i am just not getting...
echo $rec->exportTo('JSON'); //export to JSON string (new in Propel 1.6)
}
}
我在深入研究推进文档和源代码,我还没有把我的头围绕在整个Peer/TableMap/RelationMap/etc模型上,而且我已经接近了一个现成的解决方案,但一直在死路一条。
但这似乎不是一个非常独特的概念,我试图在这里实现,所以我希望有一个推动大师,谁可以迅速指出我在这方面的弱智。
谢谢!
编辑:(响应wimvds的评论)通用方法的目标是允许我在数据库级别配置关系,然后推动PHP类,并将它们作为对象使用,而不必担心底层的数据存储。
通过一种特定的方法,我必须在DB中定义这些关系,然后编写一个自定义的“水合”函数(如上面所列),以便从数据存储中正确地检索对象。这种方法的哲学问题是复制,如果我改变了数据库中的关系,然后重新运行propel-gen,那么我还必须更新我的水化函数,以反映结构上的变化。似乎所有的片段都应该在那里,以允许跳过最后一步并删除复制。
例如,使用上面这个小的特定情况的水化函数,我所做的就是根据我头脑中关于英雄和技能的知识调用getWHATEVER()助手函数,当我得到一个英雄时,我想检查hero_skill并得到相应的技能列表。Propel也知道这些关系,因为Foreign,并且当使用joinWith()时它甚至知道递归(将递归对象引用设置为字符串值‘*递归’),所以所有的部分都已经就绪,以推动这些对象智能地自动水合物,同时优雅地解析/忽略递归,我只是找不到合适的语法来实现。
ie:获取一个对象,解析它的FK关系,水合物所有‘子’对象(由FK在相关表中的行),并排除递归对象。
我想我要寻找的是一种完全抽象数据存储的方法,利用Propel基于数据库schema.xml定义的类生成能力,因此不必定制编写一组可能会在数据结构更改时发生更改的助手函数。因此,允许我根据对象而不是数据库记录进行编码,这不是ORM的全部要点吗?
我希望这能澄清一点,谢谢!
发布于 2011-03-04 10:15:37
我想您可以尝试使用isCrossRef表属性来简化查询/水处理。
请参阅:http://www.propelorm.org/wiki/Documentation/1.5/WhatsNew#Many-to-ManyRelationships
https://stackoverflow.com/questions/5188528
复制相似问题