Невозможно получить красноречие для автоматического создания объединений
Извините заранее, если ответ на мой вопрос очевиден. Я проделал свою должную осмотрительность в исследовании этой темы, прежде чем я разместил здесь.
Большая часть моего опыта работы с картой исходит от использования CodeIgniter, поэтому у меня никогда не было практического опыта использования ORM. (У CI есть некоторые готовые ORM-решения, но я их никогда не использовал.)
Я хотел бы использовать встроенную функциональность ORM в Laravel Rloquent ORM для автоматического объединения таблиц турниров и стран вместе при выполнении запроса и возврата набора данных, который также включает данные о турнире как соответствующие данные по стране.
То есть, я хочу, чтобы Eloquent автоматически распознавал отношения внешнего ключа, чтобы я мог просто запустить запрос (например, Tournament:: with ('Country') → all()), который вернет весь набор турниров и данные по стране.
Пожалуйста, остановите меня прямо сейчас, если я использую Eloquent таким образом, чтобы он никогда не предназначался для использования! Моя путаница может быть больше о том, как я пытаюсь смять несостоятельное решение, а не синтаксис или ошибку кодирования.
Запрос, который я хотел бы реплицировать в "Красноречивый"
SELECT * FROM tournaments LEFT JOIN countries ON tournaments.country_id = countries.id
Ожидаемый результат в PHP
Я ожидаю получить массив объектов турнира (в PHP), где будет выглядеть один объект турнира:
- tournaments.id
- tournaments.year
- tournaments.country_id
- tournaments.created_at
- tournaments.updated_at
- countries.id
- countries.code
- countries.name
- countries.url
- countries.created_at
- countries.updated_at
Неудачные Attemps, которые я сделал до сих пор
Я выполнил все эти попытки в методе фиктивного контроллера и вывел результат в виде форматированной строки в профилировщик.
Ошибка при попытке # 1:
PHP-код в фиктивном контроллере:
$tournaments = Tournament::with('Country')->all();
Создает следующий запрос:
SELECT * FROM `tournaments`
Результат # 1 возвращает:
Массив, содержащий объекты турнира, которые включают только столбцы в таблице турниров.
Не удалось выполнить попытку # 2
PHP-код в фиктивном контроллере:
$tournaments = Tournament::with('Country')->first();
Вызывает следующую ошибку:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'tournament_id' in 'where clause'
SQL: SELECT * FROM `countries` WHERE `tournament_id` IN (?)
Bindings: array (
0 => '1',
)
Другие неудачные попытки
Я пробовал различные комбинации соглашений об именах (например, столбцы, таблицы и т.д.) безрезультатно. Я также попытался создать запрос в Fluent, который работал нормально, но мне потребовалось указать соединения, которых я пытаюсь избежать.
Моя окружающая среда
- PHP: 5.3.13
- MySQL: 5.1.53
- Laravel: 3.2.3
Связь между таблицами
- отношения "один-к-одному"
- В турнире должна быть страна (есть ограничение внешнего ключа, чтобы обеспечить ее соблюдение).
- Страна может принадлежать многим другим отношениям (например, участник, не показан здесь, имеет страну рождения).
Таблица стран
CREATE TABLE `countries` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(4) NOT NULL,
`name` varchar(25) NOT NULL,
`url` varchar(25) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `countries_code_unique` (`code`),
KEY `countries_url_index` (`url`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=latin1
Таблица турниров
CREATE TABLE `tournaments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`year` int(11) NOT NULL,
`country_id` int(11) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `tournaments_year_unique` (`year`),
KEY `tournaments_country_id_foreign` (`country_id`),
CONSTRAINT `tournaments_country_id_foreign` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=latin1
Страны Модель (countries.php)
class Country extends Eloquent {
public static $timestamps = true;
public static $table = 'countries';
}
Модель турниров (tournament.php)
class Tournament extends Eloquent {
public static $timestamps = true;
public function country()
{
return $this->has_one('Country');
}
}
Ответы
Ответ 1
Ясно, что with('Country')
или with('Country')
не отличается от того, что ему удалось получить следующую ошибку:
Column not found: 1054 Unknown column 'tournament_id' in 'where clause'
SQL: SELECT * FROM `countries` WHERE `tournament_id` IN (?)
Неправильно то, как определяется связь: Турнир должен иметь страну, которая должна принадлежать стране, и не имеет одной страны. Итак, чтобы решить это изменение, отношение к
public function country()
{
return $this->belongs_to('Country');
}
Ответ 2
Согласно документам Eloquent:
Примечание. Все методы, доступные в построителе запросов, также доступны при запросе моделей Eloquent.
Итак, имея в виду что-то вроде:
DB::table("tournament")->join("countries","tournaments.country_id","=","countries.id")->get();
Должен быть реплицируемым в "Красноречии". Я лично использую версию построителя запросов только сейчас, которую вы, возможно, захотите использовать, но я попытаюсь проверить с помощью Eloquent, когда я получу шанс и обновить это.
UPDATE:
Да, используя методы создания запросов Eloquent, вы можете:
Tournament::join("countries","tournaments.country_id","=","countries.id")->get();
Это вернет модель турнира, которая включает в себя поля обеих таблиц.
НТН
Ответ 3
В предложении 'with' запрашивается "Страна", но ваш код объявляет его "страной".
Итак, если:
$tournaments = Tournament::with('Country')->all();
Be:
$tournaments = Tournament::with('Country')->all();
Потому что в вашей модели турниров вы определили это как:
public function country()
{
return $this->has_one('Country');
}
Помогает ли это изменение?
Ответ 4
Вы должны убедиться, что ваши отношения объявлены в вашей модели турнира:
public function country() {
return $this->has_one('Country');
}
Кроме того, вам придется объявить обратное в вашей модели страны:
public function tournament() {
return $this->belongs_to('Tournament');
}
На этом этапе вы можете получить доступ к объекту турнира, связанному с объектом страны, следующим образом:
$tournaments = Tournament::with('country')->all();
foreach ($tournaments as $tournament) {
echo $tournament->country;
}
Сообщите мне, отобразите ли вы каждую соответствующую страну на турнир.