我在Doctrine / symfony中有一个数据模型。我有一个'课程',有许多'课程'。对于每节课,我需要计算课程出现的顺序(按日期)。例如,“初学者的Java课程”可能在10月份有10节课,我需要检索这些课程的顺序,以便第一个被称为“Java for beginners 1”等。
目前,我的Lesson模型中有一个getTitle()方法,用于查询数据库以建立数字。这很好用。但是,当屏幕上有400个课程时(这是一个典型的用例),它会产生400多个查询。
我已经阅读了有关教条行为的内容,据我了解,我可以在每次添加,编辑或删除课程时添加一个行为我可以重新计算所有序列号 - 将它们存储在数据库中。但是,我不能让它有效地工作。
有没有比我提到的方法更有效的方法?
干杯,
马特
Doctrine_Query::create()->
from('Lesson l')->
leftJoin('l.Course c')->
leftJoin('l.Teacher t')->
leftJoin('l.Students sl')->
andWhere('l.date BETWEEN ? AND ?', array(date('Y-m-d', $start_date), date('Y-m-d', $end_date)))->
orderBy('l.date, l.time');
以上代码会返回我的所有课程信息(除了课程编号)。
Doctrine_Query::create()
->select('COUNT(l.id) as count')
->from('Lesson l')
->leftJoin('l.Course c')
->where('c.id = ?', $this->course_id)
->andWhere('TIMESTAMP(l.date, l.time) < ?', $this->date . ' ' . $this->time)
->orderBy('l.date, l.time');
$lessons = $q->fetchOne();
return $lessons->count + 1;
此代码作为函数在Lesson模型中。它计算给定课程的序列号并将其作为整数返回。这是被调用400次以上的方法。我尝试将其作为子查询添加到第一个查询中,但没有成功。
public function postInsert(Doctrine_Event $event) {
$invoker = $event->getInvoker();
$table = Doctrine::getTable('Lesson');
// Course query
$cq = Doctrine::getTable('Lesson')->createQuery();
$cq->select('COUNT(l.id) as count')
->from('Lesson l')
->leftJoin('l.Course c')
->where('c.id = ?', $invoker->Course->id)
->andWhere('TIMESTAMP(l.date, l.time) < ?', $invoker->date . ' ' . $invoker->time)
->orderBy('l.date, l.time');
$lessons = $cq->fetchOne();
$q = $table->createQuery();
$q->update()->
set('sequence_number', $lessons->count + 1)->
where('id = ?', $invoker->id)->
execute();
}
这里显而易见的问题是它只更新调用的课程。如果一个课程更新其序列,则所有课程都应更新其序列号。但是,当我尝试从我的灯具填充数据库时,上面的代码会导致内存问题(大约5000课,它在~1500失败)。
答案 0 :(得分:0)
编辑::
因为你吃掉所有这些物品的大量内存,你的内存耗尽。您应该尝试以1000个为一组进行批处理(因为您在~1500时失败)。
您可以做的另一件事是不直接将侦听器/行为放在模型上,而是创建一个postTransactionCommit
侦听器。在此侦听器中,您可以检查lesson
表中的任何记录是否是提交的一部分,然后以正确的顺序更新它们。
编辑:
所以根据我们的评论......让我们走向另一个方向:
Doctrine_Core::getTable('Course')->createQuery('c')
->leftJoin('l.Lesson')
->orderBy('l.date_column')
->execute();
通常,为了避免额外的查询,您将在查询中执行连接,这样您就不会有额外的费用。例如:
Doctrine_Core::getTable('Lesson')->createQuery('l')
->leftJoin('l.Course')
->orderBy('l.date_column')
->execute();
这样,课程和课程信息将在一个查询中显示,课程将与课程一起保持水分。
这当然对您的序列号没有任何作用。这真的是一个不同的问题,我认为最好的办法就是按照你自己的建议使用一种行为。如果您想发布行为代码和问题描述,我相信我们可以帮助您解决问题