Связь «Один ко многим» (One to many)

Создание таблиц

Сначала надо создать таблицы post и comment.

yii migrate/create create_posts_table --fields="title:string:notNull,content:text"
yii migrate/create create_comment_table --fields="comment:text:notNull,post_id:integer:foreignKey(post)"
yii migrate

Для поля «post_id» будет создан внешний ключ (foreign key). Он позволяет при удалении поста автоматически удалять все его комментарии на стороне MySQL.

Также надо создать модели Post и Comment.

# models/Post.php
namespace app\models;
use Yii;

class Post extends \yii\db\ActiveRecord
{
}


# models/Comment.php
namespace app\models;
use Yii;

class Comment extends \yii\db\ActiveRecord
{
}

Вывод комментариев

В файле models/Post.php надо добавить следующий код:

# models/Post.php

class Post extends \yii\db\ActiveRecord
{
    public function getComments()
    {
        return $this->hasMany(Comment::classname(), ['post_id' => 'id']);
    }
}

Теперь можно выбирать комментарии:

# controllers/PostController.php

class PostController extends Controller
{
    public function actionView()
    {
        // выборка комментариев поста
        $post = Post::findOne(1);
        $comments = $post->comments;
    }
}

Когда идёт обращение к свойству comments, происходит дополнительный SQL-запрос для выборка комментариев. Такое поведение называется «Lazy load», т.е. данные загружается тогда, когда они нужны.

Но при выборке нескольких страниц, для каждой страницы будет происходить дополнительный запрос в базу данных. Чтобы такого не происходило, рекомендуется использовать метод with(), который сразу выберет нужные комментарии при выборки страниц.

# controllers/PostController.php

class PostController extends Controller
{
    public function actionIndex()
    {
        $posts = Post::find()->with('comments')->all();
        foreach ($posts as $post) {
            // здесь SQL-запросов не будет, т.к. данные загрузились при выборке постов
            $post->comments;
        }
    }
}

Параметры

В модели можно указать параметры для выборки комментариев.

# models/Post.php

class Post extends \yii\db\ActiveRecord
{
    public function getComments()
    {
        return $this->hasMany(Comment::classname(), ['post_id' => 'id'])
            ->where(['active' => 1])->orderBy(['rating' => SORT_DESC]);
    }
}

Добавление комментария

Комментарий добавляется как обычное добавление записи.

$comment = new Comment();
$comment->comment = 'Комментарий';
$comment->post_id = 4; // ИД поста, к которому будет привязан комментарий
$comment->save();