В предыдущей части мы разобрались с установкой фреймворка и настроили ЧПУ. Сегодня продолжим изучать Yii и рассмотрим на примере как работают связи моделей и как ими пользоваться.
Для начала нужно подключиться к базе данных. Для этого переходим в файл config/db.php и устанавливаем имя БД, имя пользователя и пароль:
Предварительно я создал три таблицы в базе данных:
То есть имеются независимые пользователи, независимые организации. Но есть ещё и некие воркеры, которые одновременно являются и пользователями (соответственно, имеют связь с таблицей members), и сотрудниками какой-то конкретной организации (имеют связи с таблицей organizations).
Создадим одноимённые модели для вышеперечисленных таблиц. Пространство имён - app\models, наследуем \yii\db\ActiveRecord:
В каждую модель добавим статический метод tableName(), который будет возвращать имя таблицы БД:
Теперь переходим непосредственно к связям, которые устанавливаются с помощью метода getXxx(). Вместо Xxx указывается имя связи.
Создадим связь пользователя с его профессией:
/**
* Получить работника, которым является пользователь
*/
public function getWorker() : \yii\db\ActiveQuery
{
return $this->hasOne( Worker::class, [ 'uid' => 'id' ] );
}
В моём случае пользователь будет иметь возможность работать только в одном месте, поэтому используем метод hasOne(), в качестве параметров которого передаём название класса Worker (класс, с которым объявляем связь) и массив связных полей этих двух таблиц. Поле uid в таблице workers - это поле id в таблице members.
Далее перейдём к модели Worker и создадим обратную связь (то бишь свяжем сотрудника с конкретным пользователем):
/**
* Получить пользователя, коим является данный сотрудник
*/
public function getMember() : \yii\db\ActiveQuery
{
return $this->hasOne( Member::class, [ 'id' => 'uid' ] );
}
Меняем здесь название связи, меняем параметры метода hasOne().
Однако в эту модель нам нужно добавить ещё одну связь - связь с таблицей organizations. Это необходимо, поскольку таблица с работниками связана не только с пользователями, но и с организациями. Метод связи получается примерно таким:
/**
* Получить организацию, в которой состоит данный сотрудник
*/
public function getOrganization() : \yii\db\ActiveQuery
{
return $this->hasOne( Organization::class, [ 'id' => 'oid' ] );
}
Поле oid в таблице workers - это поле id в таблице organizations.
Последний метод связи мы добавляем в модель Organization:
/**
* Получить список сотрудников организации
*/
public function getWorkers() : \yii\db\ActiveQuery
{
return $this->hasMany( Worker::class, [ 'oid' => 'id' ] );
}
Обращаю внимание на то, что в отличие от уже написанных связей - тут используется метод hasMany(), поскольку в организации может находится несколько сотрудников.
С моделями мы закончили, переходим к контроллеру SiteController. Создадим в нём новый action с именем jobs. Также понадобится создать одноимённый файл в папке views.
И давайте попробуем найти в таблице members сотрудника с id1, запишем всё это дело в переменную $member и с помощью функции compact() передадим $member в вид:
public function actionJobs() : string
{
$member = Member::findOne( 1 );
return $this->render( 'jobs', compact( 'member' ) );
}
Перейдя в вид jobs, мы можем вывести информацию об этом пользователе:
<?= $member->name ?>
И на сайте у нас теперь выводится имя пользователя c ID 1:
Теперь воспользуемся нашими связями и выведем на экран должность этого пользователя (из таблицы workers). Если юзер не является сотрудником - появится сообщение об ошибке.
<?= $member->name . ' - ' . $member->worker->position ?>
Смотрим, что напечаталось:
А что, если нам необходимо вывести название организации, в которой находится юзер? Напомню, что связи между пользователями и организациями нет, связь есть только между работниками и организациями. А делается это, в принципе, так же:
<?= $member->name . ' работает в ' . $member->worker->organization->name ?>
Хорошо, поодиночке выводить связные данные научились, теперь попробуем вывести всех пользователей сразу (в виде таблицы). Чуть меняем запрос к БД в actionJobs():
public function actionJobs() : string
{
$members = Member::find()->with( [
'worker' => function( $query )
{
$query->with( 'organization' );
}
] )->asArray()->all();
return $this->render( 'jobs', compact( 'members' ) );
}
Если распечатать массив $members, то можно увидеть примерно следующее:
array(10) {
[0]=>
array(4) {
["id"]=>
int(1)
["name"]=>
string(31) "Дмитрий Вергасов"
["joined"]=>
int(1620211215)
["worker"]=>
array(5) {
["id"]=>
int(5)
["uid"]=>
int(1)
["oid"]=>
int(3)
["position"]=>
string(12) "Прораб"
["organization"]=>
array(2) {
["id"]=>
int(3)
["name"]=>
string(29) "ООО ПанельСтрой"
}
}
}
/* ... */
}
Ну, и наконец создадим простую таблицу, внутри которой выведем всех пользователей и их данные:
<table class="table">
<thead>
<tr>
<th>Имя пользователя</th>
<th>Зарегистрирован</th>
<th>Организация</th>
<th>Должность</th>
</tr>
</thead>
<tbody>
<?php foreach ( $members as $key => $member ): ?>
<tr>
<td><?= $member['name'] ?></td>
<td><?= date( 'd.m.Y', $member['joined'] ) ?></td>
<td><?= $member['worker']['organization']['name'] ?? 'Не трудоустроен' ?></td>
<td><?= $member['worker']['position'] ?? 'Не трудоустроен' ?></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
И вот, что у нас получилось:
На это вторая часть по изучению Yii2 завершена 🙃
Перед публикацией, советую ознакомится с правилами!
Нашли ошибку?
Вы можете сообщить об этом администрации.
Выделив текст нажмите CTRL+Enter