Краткое описание моей среды:
- Symfony: 1,4,8
- Учение: 1.2.3
- Centos 5.5 (PHP 5.3.3)
- MySQL 5.1.52
У меня есть новый проект, созданный в Symfony, и вот схема проекта:
# Car
RjCar:
actAs: { Timestampable: ~ }
columns:
id: { type: integer(4), unsigned: true, primary: true, autoincrement: true }
year: { type: integer(2), unsigned: true, notnull: true }
engine_mod: { type: string(1000) }
exterior_mod: { type: string(1000) }
suspension_mod: { type: string(1000) }
audio_mod: { type: string(1000) }
vote_pos: { type: integer(4), notnull: true, unsigned: true, default: 0 }
vote_neg: { type: integer(4), notnull: true, unsigned: true, default: 0 }
views: { type: integer(4), notnull: true, unsigned: true, default: 0 }
# Foreign keys
category_id: { type: integer(1), unsigned: true, notnull: true }
category_check: { type: boolean, notnull: true, default: 0 }
user_id: { type: integer(5) }
relations:
RjCategory: { onDelete: CASCADE, local: category_id, foreign: id, foreignAlias: RjCars }
sfGuardUser: { onDelete: CASCADE, local: user_id, foreign: id, foreignAlias: RjCars }
# Category
RjCategory:
columns:
id: { type: integer(1), unsigned: true, primary: true, autoincrement: true }
name: { type: string(255), notnull: true}
# I do not include the sfGuardUser schema, but it's the default one from the plugin
Когда я хочу получить последние 10 автомобилей с именем категории и именем пользователя, я использую следующий код в RjCarTable.class.php:
$last_cars = $this->createQuery('car')
->leftJoin('car.sfGuardUser user')
->leftJoin('car.RjCategory categ')
->orderBy('car.created_at DESC')
->limit(10)
->execute();
return $last_cars;
На моей странице все выглядит нормально, у меня есть все мои результаты, но в панели отладки я вижу 22 запроса (вместо 2, как должно быть).
Вот вывод запроса для первого, который является нормальным:
SELECT
/* Everything about the car */
r.id AS r__id,
r.year AS r__year,
r.engine_mod AS r__engine_mod,
r.exterior_mod AS r__exterior_mod,
r.suspension_mod AS r__suspension_mod,
r.audio_mod AS r__audio_mod,
r.vote_pos AS r__vote_pos,
r.vote_neg AS r__vote_neg,
r.views AS r__views,
r.type_id AS r__type_id,
r.category_id AS r__category_id,
r.category_check AS r__category_check,
r.user_id AS r__user_id,
r.created_at AS r__created_at,
r.updated_at AS r__updated_at,
/* ... hidden because irrelevant... retrieve everything about the sfGuardUser and profile... */
/* Everything about the category */
r2.id AS r2__id,
r2.name AS r2__name,
FROM rj_car r
LEFT JOIN sf_guard_user s ON r.user_id = s.id
LEFT JOIN rj_category r2 ON r.category_id = r2.id
ORDER BY r.created_at DESC
LIMIT 10
Так что до тех пор все нормально, за исключением того, что за этим запросом следуют еще 20 человек, чтобы получить информацию о каждой категории (по-видимому, 2 запроса для каждого результата), в то время как в предыдущем запросе вы можете заметить, что эта информация доступна. Я не буду помещать их все, но вот некоторые:
SELECT r.id AS r__id, r.name AS r__name FROM rj_category r WHERE (r.id = '8') LIMIT 1
SELECT r.id AS r__id, r.name AS r__name FROM rj_category r WHERE (r.id = '8') LIMIT 1
SELECT r.id AS r__id, r.name AS r__name FROM rj_category r WHERE (r.id = '9') LIMIT 1
SELECT r.id AS r__id, r.name AS r__name FROM rj_category r WHERE (r.id = '9') LIMIT 1
/* etc.. 20 times */
Итак, мои настоящие вопросы:
- Почему он выполняет все эти ненужные запросы, а первый запрос должен содержать эту информацию?
- Почему это не происходит для таблицы sfGuardUser? Соотношение между моим объектом RjCar и объектом sfGuardUser, по-видимому, такое же, как и между RjCar и RjCategory.
Если кто-то уже столкнулся с той же проблемой, я буду очень рад услышать об этом. Как я уже сказал, все работает нормально, но я предпочитаю, чтобы этот модуль не генерировал ненужных запросов, как это должно выполняться на домашней странице моего приложения.