In Yii2, Active Record (AR) allows defining relationships between tables using model classes. These relationships help in fetching related data easily without writing complex SQL queries.
Yii2 supports the following relationships:
hasOne())hasMany())A one-to-one relationship means each record in one table corresponds to exactly one record in another table.
User table (User details)UserProfile table (User's additional profile details, linked by user_id)CREATE TABLE user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL
);
CREATE TABLE user_profile (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT UNIQUE,
bio TEXT,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE
);class User extends \yii\db\ActiveRecord
{
public function getProfile()
{
return $this->hasOne(UserProfile::class, ['user_id' => 'id']);
}
}class UserProfile extends \yii\db\ActiveRecord
{
public function getUser()
{
return $this->hasOne(User::class, ['id' => 'user_id']);
}
}$user = User::findOne(1);
echo $user->profile->bio; // Accessing profile dataA one-to-many relationship means a record in one table is related to multiple records in another table.
Category table (Product categories)Product table (Each product belongs to one category, linked by category_id)CREATE TABLE category (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL
);
CREATE TABLE product (
id INT PRIMARY KEY AUTO_INCREMENT,
category_id INT,
name VARCHAR(100) NOT NULL,
FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE
);class Category extends \yii\db\ActiveRecord
{
public function getProducts()
{
return $this->hasMany(Product::class, ['category_id' => 'id']);
}
}class Product extends \yii\db\ActiveRecord
{
public function getCategory()
{
return $this->hasOne(Category::class, ['id' => 'category_id']);
}
}$category = Category::findOne(1);
foreach ($category->products as $product) {
echo $product->name . "<br>";
}A many-to-many relationship requires an intermediate table to link two related tables.
Student tableCourse tablestudent_course (Intermediate table storing student-course associations)CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL
);
CREATE TABLE course (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(100) NOT NULL
);
CREATE TABLE student_course (
student_id INT,
course_id INT,
PRIMARY KEY (student_id, course_id),
FOREIGN KEY (student_id) REFERENCES student(id) ON DELETE CASCADE,
FOREIGN KEY (course_id) REFERENCES course(id) ON DELETE CASCADE
);class Student extends \yii\db\ActiveRecord
{
public function getCourses()
{
return $this->hasMany(Course::class, ['id' => 'course_id'])
->viaTable('student_course', ['student_id' => 'id']);
}
}class Course extends \yii\db\ActiveRecord
{
public function getStudents()
{
return $this->hasMany(Student::class, ['id' => 'student_id'])
->viaTable('student_course', ['course_id' => 'id']);
}
}$student = Student::findOne(1);
foreach ($student->courses as $course) {
echo $course->title . "<br>";
}You can filter related records dynamically.
$category = Category::findOne(1);
$activeProducts = $category->getProducts()->where(['status' => 1])->all();$user = User::findOne(1);
echo $user->profile->bio; // Queries executed only when accessedwith().$users = User::find()->with('profile')->all();$category = Category::findOne(1);
$productCount = $category->getProducts()->count();$student = new Student();
$student->name = "Rahul";
$student->save();
$course = Course::findOne(2);
Yii::$app->db->createCommand()->insert('student_course', [
'student_id' => $student->id,
'course_id' => $course->id
])->execute();A self-referencing relationship is used when a table references itself, such as categories with subcategories or employees with managers.
CREATE TABLE category (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
parent_id INT NULL,
FOREIGN KEY (parent_id) REFERENCES category(id) ON DELETE SET NULL
);class Category extends \yii\db\ActiveRecord
{
// Parent category (One-to-One)
public function getParent()
{
return $this->hasOne(Category::class, ['id' => 'parent_id']);
}
// Child categories (One-to-Many)
public function getChildren()
{
return $this->hasMany(Category::class, ['parent_id' => 'id']);
}
}$category = Category::findOne(1);
echo "Parent: " . $category->parent->name;
foreach ($category->children as $child) {
echo "Child: " . $child->name . "<br>";
}Yii2 does not have built-in polymorphic relations like Laravel, but we can implement them manually.
CREATE TABLE comment (
id INT PRIMARY KEY AUTO_INCREMENT,
entity_type VARCHAR(50) NOT NULL, -- Stores the model name (Post, Product, etc.)
entity_id INT NOT NULL, -- Stores the related model's ID
content TEXT NOT NULL
);class Comment extends \yii\db\ActiveRecord
{
public function getEntity()
{
return $this->hasOne(self::getEntityClass(), ['id' => 'entity_id']);
}
private static function getEntityClass()
{
$entityType = static::findOne(['id' => $this->id])->entity_type;
return $entityType === 'Post' ? Post::class : Product::class;
}
}$comment = Comment::findOne(1);
echo $comment->entity->title; // Works for both Post and ProductIf a table has a composite primary key, you can define relationships using both keys.
CREATE TABLE order_item (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id),
FOREIGN KEY (order_id) REFERENCES orders(id),
FOREIGN KEY (product_id) REFERENCES product(id)
);class Order extends \yii\db\ActiveRecord
{
public function getOrderItems()
{
return $this->hasMany(OrderItem::class, ['order_id' => 'id']);
}
}class OrderItem extends \yii\db\ActiveRecord
{
public function getProduct()
{
return $this->hasOne(Product::class, ['id' => 'product_id']);
}
public function getOrder()
{
return $this->hasOne(Order::class, ['id' => 'order_id']);
}
}$order = Order::findOne(1);
foreach ($order->orderItems as $item) {
echo $item->product->name . " - Quantity: " . $item->quantity . "<br>";
}| Relationship Type | Yii2 Method | Example |
|---|---|---|
| One-to-One | hasOne() | User → Profile |
| One-to-Many | hasMany() | Category → Products |
| Many-to-Many | hasMany()->viaTable() | Students ↔ Courses |
| Self-Referencing | hasOne() (Parent), hasMany() (Children) | Categories with Subcategories |
| Polymorphic | Custom Logic | Comments on Post/Product |
| Composite Key | hasMany() with both keys | Order ↔ Order Items |
Yii2 provides a flexible and powerful way to manage relationships in Active Record. The ability to define relationships using hasOne(), hasMany(), and viaTable() makes querying related data seamless.
Sign in to join the discussion and post comments.
Sign in