Kohana 3.2 ORM问题

时间:2013-05-26 16:35:35

标签: kohana kohana-3.2

让我们总结一下我想问的问题。

我有一个类别表和一个新闻表。

因此,类别可以包含许多新闻以及子类别。如果我删除一个类别,代码需要找到该类别的子类别以及与该类别相关的新闻以及要删除的子类别。目前我的代码看起来如此(目前运作良好):

关系:

public $_has_many = array(
        'news' => array(
            'model'         =>  'news',
            'foreign_key'   =>  'cat_id'
        )
    );   

要删除的代码:

/*
     *  @param $ids: The array of category id that we want to delete
     */
    public function delete_items($ids){

        if(!is_array($ids))
            $ids = array($ids);

        if(is_array($ids)){
            $recursive = new System_Recursive();
            /*
             *  list_items() method will simply return all records for the category table
             */
            $source = $this->list_items(null);

            /*
             *  Loop through the category ids
             */
            foreach($ids as $id){

                $result = $this->where('id', '=', $id)->find();
                if($result->loaded()){

                    // If category found, then find all the news related to that category
                    $main_category_news = $result->news->find_all();
                    if($main_category_news){
                        // Loop through all the news and proccess the delete method
                        foreach($main_category_news as $main_news){
                            $main_news->delete();
                        }
                    }

                    /*
                     *  The find_children() method returns all sub categories of the current category ($result)
                     */
                    $recursive->find_children($source, $result->id, $arr_children, false);

                    if($arr_children){
                        // If any sub categories found, continue to loop :((, terrible
                        foreach($arr_children as $child){
                            $this->clear();
                            $child_result = $this->where('id', '=', $child)->find();
                            if($child_result->loaded()){
                                /*
                                 * Again, find news related to this sub category and then loop through the news to do single delete
                                 */
                                $child_news = $child_result->news->find_all();
                                foreach($child_news as $c){
                                    $c->delete();
                                }
                            }
                            /*
                             *  After deleting news for sub category, 
                             *  I use clear to prevent error from loaded object
                             *  Then find "again" the sub category to delete it
                             */
                            $this->clear();
                            $child_delete = $this->where('id','=',$child)->find();
                            if($child_delete->loaded()){
                                $child_delete->delete();
                            }
                        }
                    }

                    /*
                     *  And finally for the main direct category 
                     */
                    $this->clear();
                    $result = $this->where('id', '=', $id)->find();
                    $result->delete();
                }
            }
        }

代码中有很多循环,让我们考虑删除50个类别中的5个类别,每个类别都有500个新闻。我不知道,但我认为这需要一整天才能完成任务。

所以,有人能给我一些以正确方式完成此代码的提示:如何减少代码量?如何减少循环?在这种情况下是否有可能创建一个重用的函数,例如,如果新闻有很多标签,我们会在这里做同样的事情,只需调用该方法就可以了吗?

请帮我解决这个问题。如果你没有回答,请告诉我你为什么不这样做,这样我就可以提出更有意义的问题。

谢谢

2 个答案:

答案 0 :(得分:1)

如果在Model函数中编写纯SQL查询可能会更快,就像这样

$query = DB::query(Database::DELETE, 'DELETE FROM news WHERE news.id IN
(
SELECT news.id FROM news
JOIN sub_category ON news.sub_category_id = sub_category.id
JOIN category ON sub_category.category_id = category.id
WHERE category.id = '.$this->id.'
)'
);

我不确定您的确切数据库设计,因此您可能需要更改SQL代码,但您可以获得主要想法。

答案 1 :(得分:0)

假设您正在使用InnoDB(很可能)。由于foreign key constraints,您不需要任何PHP代码。

有很多教程,解决方案正在使用

ON UPDATE CASCADE
ON DELETE CASCADE

创建父级外键时。更新父级时,所有外键也将更新(如果需要,通常在id更改时),如果删除父级,所有子项也将被删除。