Ну, я вообще не проверял это, но я, вероятно, с большей вероятностью напишу ваш код более похожим на это; надеюсь, это даст вам несколько идей:
function find_daily() {
$connection = Doctrine_Manager::connection();
$connection->setCharset('utf8');
// Make sure "today" doesn't change while the script runs
$today = date("Y-m-d");
// Find an image with today's date.
$q = Doctrine_Query::create()
->from('Image')
->where('daily_date = ?', $today)
->limit(1);
$image = $q->fetchOne();
if (!$image) {
// There was no image with today's date, so pick one from the queue at random instead.
$q = Doctrine_Query::create()
->from('Image')
->where('daily_date = ?', "0000-00-00")
->andWhere("dir =?","queue")
->orderBy("rand()")
->limit(1);
$image = $q->fetchOne();
// ToDo: Cope with there being no image in the queue
$image->setDailyDate($today);
$image->setDir("archive");
$image->save();
}
return $image;
}
Однако вам нужно подумать о том, что произойдет, если два человека ударили по вашему сценарию одновременно. В этом случае они могут оба получить новое изображение для дня (поскольку каждый из них может запустить первый SELECT
одновременно, и оба получат результат, который говорит, что дневного изображения еще нет.)
Чтобы избежать этого, я думаю, вы захотите обернуть это в транзакцию и установить уровень изоляции транзакции таким образом, чтобы первый вызывающий функцию "выиграл" условие гонки, а последующие блокирующие блоки до обновления безопасно сохранено. Не совсем уверен, как бы вы поступили с Doctrine, но это не должно быть сложно.
Проверка руководства, beginTransaction()
в начале, commit()
в конце и настройка перед всем, что связано с $tx = $conn->transaction; $tx->setIsolation('SERIALIZABLE');
(в противном случае два пользователя, возможно, все еще могут запустить SELECT одновременно), вероятно, будут все вам нужно, но вы можете подождать, пока кто-то, кто действительно знает Доктрину, прокомментирует это ...
Я также сохранил дату «сегодня» в начале скрипта, в противном случае существует опасность того, что она будет отличаться во время SELECT и более поздних обновлений, если скрипт будет выполняться в полночь.