Yii2 связать таблицы

Обновлено: 15.04.2024

Здравствуйте!
Изучаю Yii2-фреймворк, дошёл до работы с базой данных.

Генерирую CRUD при помощи gii, в контроллере появляется функция findModel, в которой есть такой запрос:
$model = Pages::findOne($id)
Эта строчка возвращает данные из таблицы по ID.
Мне нужно получить данные из связанной таблицы, я делаю так:

Но при этом данные выбираются только из первой таблицы (нужно получить поля и из второй).

В связи с этом возникает 2 вопроса:
1. Обращение к базе данных в контроллере - это вообще нормально? (Всегда думал, что это прерогатива модели, но раз это реализовано на уровне фреймворка? Вообще, мной написанную логику думаю перенести в модель)
2. Как вывести поля связанной таблицы? Где-то нужно изначально указывать, что они существуют? Помогите разобраться!

Создать связь c моделью getContents(). После этого можно обратиться к атрибутам связанной таблицы через связь: $model->getContents()

Отвечу на свой вопрос, вдруг кому-то пригодится.

Итак, задача:
Есть таблица pages и связанная таблица content, в таблице content может быть несколько записей с одним page_id.
Нужно реализовать список всех pages, при клике на "edit page" мы должны попасть на страницу с контентом этой page.

Реализация:
Заходим в gii, создаём модель для pages, если поставить галочку Generate Relations, в моделе создастся функция

Создаём модель для Content.
Создаём CRUD для Pages.

В контроллере Pages меняем строчку
$model = Pages::findOne($id)
на

Всё. Можем работать с данными из таблицы content.

Первый вопрос - можно ли пихать такое в контроллер - остаётся открытым.
Вернее, я уверен, что не стоит.

Этот раздел расскажет о том, как создать новую страницу, отображающую данные по странам, полученные из таблицы countries базы данных. Для достижения этой цели вам будет необходимо настроить подключение к базе данных, создать класс Active Record, определить action и создать view.

Изучив эту часть, вы научитесь:

  • Настраивать подключение к БД.
  • Определять класс Active Record.
  • Запрашивать данные, используя класс Active Record.
  • Отображать данные во view с использованием пагинации.

Обратите внимание, чтобы усвоить этот раздел, вы должны иметь базовые знания и навыки использования баз данных. В частности, вы должны знать, как создать базу данных и как выполнять SQL запросы, используя клиентские инструменты для работы с БД.

Подготавливаем базу данных ¶

Для начала создайте базу данных под названием yii2basic , из которой вы будете получать данные в вашем приложении. Вы можете создать базу данных SQLite, MySQL, PostgreSQL, MSSQL или Oracle, так как Yii имеет встроенную поддержку для многих баз данных. Для простоты, в дальнейшем описании будет подразумеваться MySQL.

После этого создайте в базе данных таблицу country и добавьте в неё немного демонстрационных данных. Вы можете запустить следующую SQL инструкцию, чтобы сделать это:

На данный момент у вас есть база данных под названием yii2basic и внутри неё таблица country с тремя столбцами, содержащими десять строк данных.

Настраиваем подключение к БД ¶

Перед продолжением убедитесь, что у вас установлены PHP-расширение PDO и драйвер PDO для используемой вами базы данных (например, pdo_mysql для MySQL). Это базовое требование в случае использования вашим приложением реляционной базы данных. После того, как они установлены, откройте файл config/db.php и измените параметры на верные для вашей базы данных. По умолчанию этот файл содержит следующее:

Файл config/db.php — типичный конфигурационный инструмент, базирующийся на файлах. Данный конфигурационный файл определяет параметры, необходимые для создания и инициализации экземпляра yii\db\Connection, через который вы можете делать SQL запросы к подразумеваемой базе данных.

Подключение к БД, настроенное выше, доступно в коде приложения через выражение Yii::$app->db .

Информация: файл config/db.php будет подключен главной конфигурацией приложения config/web.php , описывающей то, как экземпляр приложения должен быть инициализирован. Для детальной информации, пожалуйста, обратитесь к разделу Конфигурации.

Если вам необходимо работать с базами данных, поддержка которых не включена непосредственно в фреймворк, стоит обратить внимание на следующие расширения:

Создаём потомка Active Record ¶

Чтобы представлять и получать данные из таблицы country , создайте класс — потомок Active Record, под названием Country и сохраните его в файле models/Country.php .

Класс Country наследуется от yii\db\ActiveRecord. Вам не нужно писать ни строчки кода внутри него! С кодом, приведённым выше, Yii свяжет имя таблицы с именем класса.

Информация: Если нет возможности задать прямую зависимость между именем таблицы и именем класса, вы можете переопределить метод yii\db\ActiveRecord::tableName(), чтобы явно задать имя связанной таблицы.

Используя класс Country , вы можете легко манипулировать данными в таблице country , как показано в этих фрагментах:

Информация: Active Record — мощный способ доступа и манипулирования данными БД в объектно-ориентированном стиле. Вы можете найти подробную информацию в разделе Active Record. В качестве альтернативы, вы также можете взаимодействовать с базой данных, используя более низкоуровневый способ доступа, называемый Data Access Objects.

Создаём Action ¶

Для того, чтобы показать данные по странам конечным пользователям, вам надо создать новый action. Вместо размещения нового action'a в контроллере site , как вы делали в предыдущих разделах, будет иметь больше смысла создать новый контроллер специально для всех действий, относящихся к данным по странам. Назовите новый контроллер CountryController , и создайте action index внутри него, как показано ниже.

Сохраните код выше в файле controllers/CountryController.php .

Action index вызывает Country::find() . Данный метод Active Record строит запрос к БД и извлекает все данные из таблицы country . Чтобы ограничить количество стран, возвращаемых каждым запросом, запрос разбивается на страницы с помощью объекта yii\data\Pagination. Объект Pagination служит двум целям:

  • Устанавливает пункты offset и limit для SQL инструкции, представленной запросом, чтобы она возвращала только одну страницу данных за раз (в нашем случае максимум 5 строк на страницу).
  • Он используется во view для отображения пагинатора, состоящего из набора кнопок с номерами страниц, это будет разъяснено в следующем подразделе.

В конце кода action index выводит view с именем index , и передаёт в него данные по странам вместе c информацией о пагинации.

Создаём View ¶

Первым делом создайте поддиректорию с именем country внутри директории views . Эта папка будет использоваться для хранения всех view, выводимых контроллером country . Внутри директории views/country создайте файл с именем index.php , содержащий следующий код:

View имеет 2 части относительно отображения данных по странам. В первой части предоставленные данные по странам выводятся как неупорядоченный HTML-список. Во второй части выводится виджет yii\widgets\LinkPager, используя информацию о пагинации, переданную из action во view. Виджет LinkPager отображает набор постраничных кнопок. Клик по любой из них обновит данные по странам в соответствующей странице.

Испытываем в действии ¶

Чтобы увидеть, как работает весь вышеприведённый код, перейдите по следующей ссылке в своём браузере:

Список Стран

В начале вы увидите страницу, показывающую пять стран. Под странами вы увидите пагинатор с четырьмя кнопками. Если вы кликните по кнопке "2", то увидите страницу, отображающую другие пять стран из базы данных: вторая страница записей. Посмотрев внимательней, вы увидите, что URL в браузере тоже сменилось на

За кадром Pagination предоставляет всю необходимую функциональность для постраничной разбивки набора данных:

  • В начале Pagination показывает первую страницу, которая отражает SELECT запрос стран с параметрами LIMIT 5 OFFSET 0 . Как результат, первые пять стран будут получены и отображены.
  • Виджет LinkPager выводит кнопки страниц используя URL'ы, созданные Pagination. Эти URL'ы будут содержать параметр запроса page , который представляет различные номера страниц.
  • Если вы кликните по кнопке "2", сработает и обработается новый запрос для маршрута country/index . Таким образом новый запрос стран будет иметь параметры LIMIT 5 OFFSET 5 и вернет следующие пять стран для отображения.

Заключение ¶

В этом разделе вы научились работать с базой данных. Также вы научились получать и отображать данные с постраничной разбивкой с помощью yii\data\Pagination и yii\widgets\LinkPager.

В следующем разделе вы научитесь использовать мощный инструмент генерации кода, называемый Gii, чтобы с его помощью быстро осуществлять некоторые часто используемые функции, такие как операции Create-Read-Update-Delete (CRUD) для работы с данными в таблице базы данных. На самом деле код, который вы только что написали, в Yii может быть полностью сгенерирован автоматически с использованием Gii.

5a29205045626202192076.jpg

Нужно, чтобы нажимая на РФПЛ, выводились команды из таблицы "club". С новостями все получилось, а вот дальше, что то не могу понять, как сделать подключение к еще одной таблице. Подскажите пожалуйста. В Yii2 новичок, буду благодарен за разжеванный ответ. Документацию пожалуйста не предлагать

Вот все подключения и вывод:

CategoryController:

model\Category:

category/view: вывод новостей

формирование левого меню

  • Вопрос задан более трёх лет назад
  • 1363 просмотра

Простой 7 комментариев

slo_nik

Добрый день.
Обязательно скрины вставлять, просто код вставить - религия не позволяет?
Вот, тут всё расписано, как связать таблицы.

slo_nik

slo_nik, Ну если я правильно понял, то уже делал так, не работало. Видимо не так что то делал. Спасибо, посмотрю

slo_nik

slo_nik,
В CategoryController

в models\Category


Дальше создал новый вид club и в нем:


Я наверное не так это все понимаю. Просто правда не понимаю как это все сделать. Извините за мою тупость

slo_nik

slo_nik

Добрый день! Извините за беспокойство. Еще один вопрос у меня возник, вчера вы мне помогли. направили на нужный путь, хотел бы еще к вам обраться.

Проблема такая, не могу никак понять, как обработать вывод ошибок через if else.

Код немного переработал, работает все, но без вывода текста об отсутствие команд либо новостей


Я понимаю, что нужно что то еще проверить, а что, не доходит никак.

slo_nik

nikitinandrey1990, доброе утро.
Сразу не могу сказать, как правильно сделать, так как вижу кусочек представления.
Как Вы передаёте данные в вид?

Доброе утро. Что то не могу никак понять, как работать со связанными таблицами, есть 3 таблицы:

5b2b5a5e8863b413244862.jpg

5b2b5a992e3e9149403343.jpg

5b2b5a8658dc9905999697.jpg

Как вы поняли, social и user я объединил в одну таблицу social_users, чтобы потом было удобнее динамически обновлять данные. Но вот проблема, я никак не могу понять, как выводить данные во вью из этой таблицы, чтобы автоматом все данные брались из связанных таблиц по их id. Уверен что ответ на поверхности как обычно, но найти никак не могу, помогите пожалуйста.

И вот связи в моделях:

5b2b5d147095b239134046.jpg

Я понимаю, что я получаю вообще все данные из таблицы, и они никак не привязаны ни к пользователю, ни к таблице с соц сетями. Как работают вообще эти связи, и зачем они?

  • Вопрос задан более трёх лет назад
  • 584 просмотра

kimono

спасибо за ответ, но не думаю, что это то, что мне нужно. Связи у меня есть с таблицами, как получать информацию из них, не понятно. Если никак, то тогда смысл связей в моделях, не понятно, буковки ради буковок

kimono

Дмитрий Ким, все очень хорошо описано в вопросе. Нужно связать 2 таблицы в одну SocialUsers, чтобы обращаясь к ней, получать данные из двух других. Связи настроены в моделях, но Yii не берет данные как должен.

a_u_sinitsin

Дмитрий Ким, Неохота создавать вопрос из-за мелочи, может подскажете заодно.

Есть таблица связи между пользователями с тремя полями parent_id, user_id, type.
Type может принимать два значения CHILD = 1, PARTNER = 2

Вопрос как получить всех CHILD или PARTNER? Пробовал указать return $this->hasMany(Link::class, ['parent_id' => 'id', 'type' => CHILD); но type не принимается.

myks92

Александр Синицын, чтобы добавить в связь условие выборки воспользуйтесь ->andWhere([‘type’=>’CHILD’])

Однако лучше вынести само название не в связь, а в константу. И уже подставлять константу. Потому что может измениться значение и приклеится менять везде.

kimono

Тогда используйте связи из сводной:

Дмитрий Ким, а откуда $pivot? Простите что задалбливаю) Я сам себя задолбал уже тупить)))))) Ну не могу я понять как они там между собой коннектятся. Все вот так как вы пишите пишу, пустой массив выходит в дебагере. Может Yii уже не работает так? И надо как то по другому связи прописывать?

kimono

ProFM, есть два незнакомых человека Иван и Пётр, у них есть общий друг Фёдор. Фёдор в этом случае - и есть связь между Иваном и Петром. Иван не может обращаться напрямую к Петру, только через Фёдора. Чтобы узнать фамилию Петра, Ивану нужно обратиться к нему через Фёдора:
ФАМИЛИЯ_ПЕТРА = Иван->привет, Фёдор, передай трубку Петру->привет, Пётр->скажи свою ФАМИЛИЮ
Тут Фёдору поднадоело постоянно передавать трубку, он сделал переадресацию от Ивана к Петру. Теперь логика такая:
ФАМИЛИЯ_ПЕТРА = Иван->звонит Фёдору, но там стоит переадресация на Петра->привет, Пётр->скажи свою ФАМИЛИЮ
Иначе говоря, связь, созданная Фёдором, позволяет Ивану обращаться к Петру "напрямую":
ФАМИЛИЯ_ПЕТРА = Иван->X->привет, Пётр->скажи свою ФАМИЛИЮ

А на счёт массива в дебагере - вам написали ниже:

Дмитрий Ким, Еще раз попробую обьяснить что я хочу))

У человека есть

5b2b80d5c14cc926229457.jpg

На странице выводится информация, и в том числе список соц сетей пользователя, которые он добавил на страницу, этот список я хочу получить из бд, связав текущего пользователя и таблицу social_users, где user_id будет равен id_user из таблицы user. Но тут еще нужно приравнять к таблице social_users информацию из таблицы social.

И должно получится так, если пользователь такой в таблице social_users то у него проверяются, есть ли social_id если такое есть, то должна браться информация из social со всеми ее данными которые равны этому id. И форичем выводиться во вью

В этом во всем мне не понятно, как связать таблицы так, чтобы фреемворк все эти связи понял, и дал мне всю нужную информацию

Дмитрий Ким, это тут не причем


Оно не относится к этой части когда и не связана с тем, что мне нужно. asArray я убрал но результата нет. Да и обьектами не хочется получать данные, нагрузка увеличивается

кстати тут будет только одна, откуда там все должны появиться? findOne возвращает одну строку. Уже проверил. а с find->where не работает.

Дмитрий Ким, не могу никак понять.

вот так получаю данные, но только одну, так же как и

Вставляю all ничего не выводит. В чем может быть проблема, помогите пожалуйста. Уже устал, и доку почитал, там немного не то, что мне нужно.

kimono


вот так что то получилось, но мне нужно как раз таки обращаться к


потому что если конектится к 2-м другим таблицам, он берет только данные с social_users т.е. только id. как я по ним получу все имена и адреса из таблицы social?

В вопросе ведь написано, и про таблицы, и про связи, и еще раз в комментариях объяснил. Нету связей между User и Social иначе не было бы смысла создавать еще одну таблицу.

5b2c77bd58a68707918754.jpg

Отрабатывает то нормально, берет данные только принадлежащие этому юсеру, но не от туда. Такой запрос можно было и без связей сделать

Дмитрий Ким, ладно. я так понял этот фреемворк ничего не может реализовать сложного, создан для 2-х страничного сайта без динамики.

kimono

ProFM, у вас есть по крайней мере одна из следующих проблем:
- вы не понимаете связей между таблицами
- вы не можете объяснить то, что хотите получить
- вы сами не знаете что хотите
Прежде чем делать поспешные и даже неверные выводы о фреймворке, начните с его изучения, а не с некорректного использования. Если фреймворк не решает вашу проблему - в 90% случаев - это ваша вина.

Дмитрий Ким, Я как раз таки все отлично объяснил. Если вы этого не поняли или не захотели читать и нормально объяснить, это не ко мне вопросы! Проблем во мне нет никаких!
То что фреемворк не может связать нормально таблицы, не моя вина. Я прописал все так, как говорится в доке, он мне возвращает пустой массив.

Вы же каким то макаром начали связывать то, что вообще никак не должно связываться. Скорее всего просто не смотрели вопрос, ответили ради ответа, а не помощи, как обычно тут и бывает.

Не смогли помочь,это логично, и начали набрасываться на человека, что он не знает что хочет. Возможно просто вы не понимаете ничего в этом, а просто скопировали информацию из доки или интернета и поменяли данные на мои, и то, только частично.

Ни один ваш ответ не может никак помочь, я не совсем чайник в этом, единственное что я просил, это помочь со связями, все остальное отлично работает.

И еще раз повторюсь, был бы нормальный фреемворк, все заработало бы, так как я все брал из доки, а значит это не моя вина, что ничего не связывается как должно..

kimono

ProFM, я не знаю, как у вас это может не работать, если работает у других.
Еще раз:

чтобы отобразить список пользователей со списком их социальных сетей делаем так:

чтобы отобразить список социальных сетей со списком их пользователей делаем так:

Я не знаю, как еще понятнее вам объяснить. При отображении социальных сетей пользователя и при отображении пользователей социальных сетей не нужно вообще использовать SocialUser, вся магия происходит в связях.

Дмитрий Ким, хоспаде. зачем читать что пишут люди, когда можно копировать код и издеваться над ними. Все разложил по полочкам и опять это же. какая может быть связь моделей user и social? Там априори не может быть никакой связи. Как вы себе предстваляете будет обновляться информация если я в юсер добавлю столбец social_id?

еще раз повторю, хотите помочь, читайте вопрос внимательно, не хотите, не нужно этого делать. Мне и без вас тут проблем хватает, издевки не намерен терпеть!

тупо скопирован код из доки, все ясно. Ни одной строчки моей нет, вопрос не прочтен. зачем вы тут такие нужны.

Я не знаю, как еще понятнее вам объяснить. При отображении социальных сетей пользователя и при отображении пользователей социальных сетей не нужно вообще использовать SocialUser, вся магия происходит в связях.

ахахах) ясно, в магии)))))))) конеееечно, не нужно ее брать)))))))))) Хорош уже)))))))))) Не смешно уже ни капли. Конечно надо 300 раз подключаться в user когда есть идентити который уже подключается к юзер, но даже не в этом дело, а в том, что там никогда не будет никакой связи с соц сетями. хотя что я обьясняю, профи умеет копировать доку, и думает что он прав))) не будем мешать. как у меня горит от таких. выучите для начала сами фреемворк, потом учите других

Дмитрий Ким, да да да)) Когда поможете, нормально, тогда и будем пользоваться))) Сейчас бы связывать не существующие колонки)))))))

я не могу))))))) когда там и в помине нет ни id ни social_id.

Уперлись вы, не хотя прочитать нормально вопрос, посмотреть таблицы, и что пишу я))) втирая эту дичь, которая не работает и не будет никогда работать

В статье рассмотрим функции и приведем примеры работы со связанными таблицами. Рассмотрим таблицу Country (Страны) известную нам из предыдущих 2 статей. Таблица включает в себя поля номер (id), название страны (name), количество жителей (number) и площадь (area).


К таблице со странами добавим подчиненную таблицу City (города). Связь между таблицами определяется как один ко многим, одна страна включает несколько городов.


Таблица содержит 3 поля это Номер (id), название города (cname) и внешний ключ соединяющий эту таблицу с родительской таблицей страны (fkey).

With(), JoinWith()

with(), JoinWith() функции связи таблиц. Выберем все страны и соответсвующие им города. Перед тем как работать со связями у нас в модели Country необходимо прописать функцию связи

Напишем запрос для вывода данных

Россия Санкт-Петербург Архангельск Москва
Румыния Бухарест Галац
США Вашингтон
Германия

InnerJoinWith()

InnerJoinWith() функция возвращает данные если есть связь между полями. Выберем все страны из таблицы Country у которых есть соответсвующие города в таблице City.

Россия Санкт-Петербург Архангельск Москва
Румыния Бухарест Галац
США Вашингтон

У Германии нет соответствующих городов, поэтому вывода ее не последовало

Join() функция связи использующаяся в построителе запросов. Выберем все страны и соответсвующие им города.

Россия Санкт-Петербург
Россия Архангельск
Россия Москва
Румыния Бухарест
Румыния Галац
США Вашингтон
Германия

Join() функция связи использующаяся в построителе запросов. Выберем все страны из таблицы Country у которых есть соответствующие города в таблице City.

Россия Санкт-Петербург
Россия Архангельск
Россия Москва
Румыния Бухарест
Румыния Галац
США Вашингтон

Можно непосредственно работать с базой данной. Перепишем последний запрос:

Россия Санкт-Петербург
Россия Архангельск
Россия Москва
Румыния Бухарест
Румыния Галац
США Вашингтон

Итак, в данной статье мы рассмотрели основные методы и привели примеры при работе со связанными таблицами в Yii 2.x

Читайте также: