如何制作模型“hasMany”和“belongsTo”? (与cakePHP相同)

时间:2011-10-01 09:57:43

标签: php cakephp activerecord

我目前正在研究我的mvc框架(在PHP中)。我看到cakePHP有能力使用“belongsTo”和“hasMany”功能。我正在尝试创建自己的功能,但遇到了问题。

假设我们有约会表(id,where,date,year_id)和年表(id,年)。我知道这个例子可以用一个没有问题的表来完成,但这只是一个例子。

class appointment_model extends model{
    public $_belongs_to= array('table'=>'year','field_connector'=>'year_id');
    public $one_value;
}

...

class year_model extends model{
    public $_has_many= array('table'=>'appointment','field_connector'=>'year_id');
    public $many_values;
}

...

class model{

private function select($query=null){
    if(!$query)die("Query cannot be null. Line num: " . __LINE__);
    $results = $this->_db->mysql_select($query);
    if(count($results)==1){
        $one = $this->initialize($results[0]);
        $this->_do_for_other_tables($one);
        return $one;
    }elseif(count($results)>1){
        $returns = array();
        foreach($results as $result){
            $one = $this->initialize($result);
            $returns[] = $this->_do_for_other_tables($one);     
        }
        return $returns;
    }else{
        return null;
    }

}


private function _do_for_other_tables(&$one, $rec=1){


    if(property_exists($this, 'many_values')){
        if(!empty($one->many_values))return;
        $many = functions::load_model($this->_has_many["table"]);
        $res = $many->find_by($this->_has_many["field_connector"], $one->id);
        $one->many_values = $res;
    }
    elseif(property_exists($this, 'one_value')){
        if(!empty($one->_belongs_to))return;
        $only_one = functions::load_model($this->_belongs_to["table"]);
        $field = $this->_belongs_to['field_connector'];
        $res = $only_one->find_by('id', $one->$field);
        $one->one_value = $res;
    }

}

}

基本上这里发生的是我进入无限循环。任何建议如何解决?如果我需要解释它,请说出来。

谢谢:)。

1 个答案:

答案 0 :(得分:1)

您的问题是您将属性“hasMany”,“belongsTo”,“hasOne”,“etc”视为简单属性,而不是将它们视为双向关系。我在许多自己的框架中所做的是由程序员手动初始化这些属性,但是当类初始化时,你检查这些属性并生成一个将两者链接在一起的对象。

创建类似System_DB_Relationship对象的类,并将相同的副本放在两个初始化模型中。如果您没有将模型实例化为工厂设计模式,则可以使用静态$ relationship模型来存储您的关系。我倾向于使用工厂/活动记录,因此最好管理这些。现在,根据模型基类的逻辑,您可能希望在关系中放置一个标记,表示“嘿,这种关系已被使用”,因此您不会再次传入它。

另一种方法是始终以降序的方式工作。也就是说,在找到hasMany时忽略它,并仅创建一个代理方法来加载子元素,但加载所有belongsTo,以便默认加载父元素。请注意,如果你有很多类,这个方法会变得很危险,所以我在我的框架中实现的通常是一个加载参数,表示加载X级关系。当你需要hasMany时,你只需使用__call()来拦截对“$ myobject-> subobjects()”的调用,然后立即加载它们。

有很多方法可以做到这一点,只需花时间手工追踪你的代码,看看没有意义的东西,尝试一些东西,你最终会得到一些东西。但正如弗朗西斯科上面所说的那样,重新发明轮子几乎没有用,除非你处理那些无法立刻改造的旧项目。把你正在做的这项工作作为一个机会,让它变得更好,并知道它是如何工作的......