NexaUI framework menyediakan cara yang fleksibel untuk mengelola hubungan antar tabel database melalui model relationships.
Dalam pengembangan aplikasi, data sering memiliki hubungan dengan data lain. Misalnya, seorang pengguna memiliki banyak posting, sebuah posting milik satu pengguna, dan sebagainya. NexaModel memungkinkan Anda untuk mendefinisikan dan bekerja dengan hubungan ini secara efisien.
Di NexaUI, relationships diimplementasikan sebagai metode dalam model yang mengembalikan data terkait.
// Model User
class User extends NexaModel
{
protected $table = 'users';
// User memiliki satu profile
public function profile()
{
return $this->Storage('profiles')
->where('user_id', $this->id)
->first();
}
}
// Model Profile
class Profile extends NexaModel
{
protected $table = 'profiles';
// Profile milik satu user
public function user()
{
return $this->Storage('users')
->where('id', $this->user_id)
->first();
}
}
// Penggunaan
$user = (new User())->Storage('users')->where('id', 1)->first();
$profile = $user ? $user->profile() : null;
// Atau sebaliknya
$profile = (new Profile())->Storage('profiles')->where('id', 1)->first();
$user = $profile ? $profile->user() : null;
Hubungan one-to-many memungkinkan satu model memiliki banyak model lain.
// Model User
class User extends NexaModel
{
protected $table = 'users';
// User memiliki banyak posts
public function posts()
{
return $this->Storage('posts')
->where('user_id', $this->id)
->get();
}
// User memiliki banyak posts aktif
public function activePosts()
{
return $this->Storage('posts')
->where('user_id', $this->id)
->where('status', 'active')
->get();
}
}
// Model Post
class Post extends NexaModel
{
protected $table = 'posts';
// Post milik satu user
public function user()
{
return $this->Storage('users')
->where('id', $this->user_id)
->first();
}
}
// Penggunaan
$user = (new User())->Storage('users')->where('id', 1)->first();
$posts = $user ? $user->posts() : [];
// Mendapatkan posts aktif saja
$activePosts = $user ? $user->activePosts() : [];
// Mendapatkan user dari post
$post = (new Post())->Storage('posts')->where('id', 1)->first();
$author = $post ? $post->user() : null;
Hubungan many-to-many menggunakan tabel pivot (junction table) untuk menghubungkan dua model.
// Model User
class User extends NexaModel
{
protected $table = 'users';
// User memiliki banyak roles melalui tabel user_roles
public function roles()
{
return $this->Storage('roles')
->join('user_roles', 'roles.id', '=', 'user_roles.role_id')
->where('user_roles.user_id', $this->id)
->get();
}
// Cek apakah user memiliki role tertentu
public function hasRole($roleName)
{
$roles = $this->roles();
foreach ($roles as $role) {
if ($role['name'] === $roleName) {
return true;
}
}
return false;
}
}
// Model Role
class Role extends NexaModel
{
protected $table = 'roles';
// Role dimiliki oleh banyak users melalui tabel user_roles
public function users()
{
return $this->Storage('users')
->join('user_roles', 'users.id', '=', 'user_roles.user_id')
->where('user_roles.role_id', $this->id)
->get();
}
}
// Penggunaan
$user = (new User())->Storage('users')->where('id', 1)->first();
$roles = $user ? $user->roles() : [];
// Cek role
if ($user && $user->hasRole('admin')) {
// User adalah admin
}
// Mendapatkan semua user dengan role tertentu
$adminRole = (new Role())->Storage('roles')->where('name', 'admin')->first();
$adminUsers = $adminRole ? $adminRole->users() : [];
// Model User dengan metode untuk mengelola roles
class User extends NexaModel
{
protected $table = 'users';
// ... metode roles() dan hasRole() seperti di atas ...
// Menambahkan role ke user
public function attachRole($roleId)
{
// Cek apakah sudah ada
$exists = $this->Storage('user_roles')
->where('user_id', $this->id)
->where('role_id', $roleId)
->exists();
if (!$exists) {
return $this->Storage('user_roles')->insert([
'user_id' => $this->id,
'role_id' => $roleId,
'created_at' => date('Y-m-d H:i:s')
]);
}
return false;
}
// Menghapus role dari user
public function detachRole($roleId)
{
return $this->Storage('user_roles')
->where('user_id', $this->id)
->where('role_id', $roleId)
->delete();
}
// Sync roles (hapus yang lama, tambah yang baru)
public function syncRoles(array $roleIds)
{
// Hapus semua role yang ada
$this->Storage('user_roles')
->where('user_id', $this->id)
->delete();
// Tambahkan role baru
$data = [];
foreach ($roleIds as $roleId) {
$data[] = [
'user_id' => $this->id,
'role_id' => $roleId,
'created_at' => date('Y-m-d H:i:s')
];
}
if (!empty($data)) {
return $this->Storage('user_roles')->insertMany($data);
}
return true;
}
}
// Penggunaan
$user = (new User())->Storage('users')->where('id', 1)->first();
// Tambah role
if ($user) {
$user->attachRole(2); // Tambah role dengan ID 2
}
// Hapus role
if ($user) {
$user->detachRole(3); // Hapus role dengan ID 3
}
// Sync roles
if ($user) {
$user->syncRoles([1, 2, 4]); // User hanya akan memiliki role 1, 2, dan 4
}
Hubungan has-many-through memungkinkan akses ke model melalui model perantara.
// Model Country
class Country extends NexaModel
{
protected $table = 'countries';
// Country memiliki banyak posts melalui users
public function posts()
{
return $this->Storage('posts')
->join('users', 'posts.user_id', '=', 'users.id')
->where('users.country_id', $this->id)
->get();
}
}
// Penggunaan
$country = (new Country())->Storage('countries')->where('id', 1)->first();
$postsFromCountry = $country ? $country->posts() : [];
Hubungan polymorphic memungkinkan model untuk terhubung ke lebih dari satu jenis model.
// Model Comment (polymorphic)
class Comment extends NexaModel
{
protected $table = 'comments';
// Comment dapat milik post atau video
public function commentable()
{
if ($this->commentable_type === 'post') {
return $this->Storage('posts')
->where('id', $this->commentable_id)
->first();
} elseif ($this->commentable_type === 'video') {
return $this->Storage('videos')
->where('id', $this->commentable_id)
->first();
}
return null;
}
}
// Model Post
class Post extends NexaModel
{
protected $table = 'posts';
// Post memiliki banyak comments
public function comments()
{
return $this->Storage('comments')
->where('commentable_id', $this->id)
->where('commentable_type', 'post')
->get();
}
// Menambahkan comment ke post
public function addComment($content, $userId)
{
return $this->Storage('comments')->insert([
'content' => $content,
'user_id' => $userId,
'commentable_id' => $this->id,
'commentable_type' => 'post',
'created_at' => date('Y-m-d H:i:s')
]);
}
}
// Model Video
class Video extends NexaModel
{
protected $table = 'videos';
// Video memiliki banyak comments
public function comments()
{
return $this->Storage('comments')
->where('commentable_id', $this->id)
->where('commentable_type', 'video')
->get();
}
// Menambahkan comment ke video
public function addComment($content, $userId)
{
return $this->Storage('comments')->insert([
'content' => $content,
'user_id' => $userId,
'commentable_id' => $this->id,
'commentable_type' => 'video',
'created_at' => date('Y-m-d H:i:s')
]);
}
}
// Penggunaan
$post = (new Post())->Storage('posts')->where('id', 1)->first();
$postComments = $post ? $post->comments() : [];
// Tambah comment ke post
if ($post) {
$post->addComment('This is a great post!', 5);
}
// Mendapatkan parent dari comment
$comment = (new Comment())->Storage('comments')->where('id', 1)->first();
$parent = $comment ? $comment->commentable() : null;
// Cek tipe parent
if ($parent) {
if ($comment->commentable_type === 'post') {
echo "Comment on post: " . $parent['title'];
} else {
echo "Comment on video: " . $parent['title'];
}
}
Untuk menghindari masalah N+1 query, NexaModel mendukung eager loading untuk relationships.
// Model User dengan eager loading
class User extends NexaModel
{
protected $table = 'users';
// User memiliki banyak posts
public function posts()
{
return $this->Storage('posts')
->where('user_id', $this->id)
->get();
}
// Mendapatkan users dengan posts (eager loading)
public function getUsersWithPosts()
{
$users = $this->Storage('users')->get();
// Collect semua user IDs
$userIds = array_column($users, 'id');
// Dapatkan semua posts untuk user-user tersebut dalam satu query
$posts = $this->Storage('posts')
->whereIn('user_id', $userIds)
->get();
// Group posts berdasarkan user_id
$postsGrouped = [];
foreach ($posts as $post) {
$userId = $post['user_id'];
if (!isset($postsGrouped[$userId])) {
$postsGrouped[$userId] = [];
}
$postsGrouped[$userId][] = $post;
}
// Assign posts ke masing-masing user
foreach ($users as &$user) {
$user['posts'] = $postsGrouped[$user['id']] ?? [];
}
return $users;
}
}
// Penggunaan
$userModel = new User();
$usersWithPosts = $userModel->getUsersWithPosts();
// Akses data
foreach ($usersWithPosts as $user) {
echo "User: " . $user['username'] . "\n";
echo "Posts: " . count($user['posts']) . "\n";
}