Models dan Repositories

NexaUI framework mengimplementasikan pola desain Repository untuk memisahkan logika akses data dari logika bisnis.

Pengenalan Model

Model dalam NexaUI adalah representasi dari data dan logika bisnis. Model bertanggung jawab untuk:

  • Mendefinisikan struktur data
  • Menangani validasi data
  • Menerapkan aturan bisnis
  • Berinteraksi dengan database melalui Repository

Contoh Model Sederhana


namespace App\Models;

use App\System\NexaModel;

class User extends NexaModel
{
    protected $table = 'users';
    
    public function getByUsername(string $username)
    {
        return $this->table($this->table)
                    ->where('username', $username)
                    ->first();
    }
    
    public function validatePassword(string $password, string $hash): bool
    {
        return password_verify($password, $hash);
    }
}
        

Repository Pattern

Repository Pattern adalah pola desain yang memisahkan logika untuk mengambil dan menyimpan data dari logika bisnis. Manfaatnya:

  • Kode yang lebih bersih dan terorganisir
  • Pemisahan yang jelas antara logika bisnis dan akses data
  • Memudahkan pengujian unit dengan dependency injection
  • Memudahkan penggantian sumber data tanpa mengubah kode bisnis

Implementasi Repository


namespace App\Models\Repositories;

use App\System\NexaRepositoryInterface;
use App\Models\Domain\UserEntity;
use App\System\NexaModel;

class NexaUserRepository implements NexaRepositoryInterface
{
    private $model;
    
    public function __construct(NexaModel $model)
    {
        $this->model = $model;
    }
    
    public function findById(int $id): ?UserEntity
    {
        $data = $this->model->table('users')->where('id', $id)->first();
        if (!$data) {
            return null;
        }
        
        return new UserEntity($data);
    }
    
    public function save(UserEntity $user): bool
    {
        $data = $user->toArray();
        
        if (isset($data['id']) && $data['id'] > 0) {
            return $this->model->table('users')
                              ->where('id', $data['id'])
                              ->update($data);
        } else {
            return $this->model->table('users')->insert($data);
        }
    }
    
    public function delete(int $id): bool
    {
        return $this->model->table('users')->where('id', $id)->delete();
    }
}
        

Domain Entities

Entity adalah objek domain yang mewakili konsep dalam domain bisnis Anda. Mereka berisi data dan perilaku yang terkait dengan entitas tersebut.

Contoh Entity


namespace App\Models\Domain;

class UserEntity
{
    private $id;
    private $username;
    private $email;
    private $password;
    private $createdAt;
    
    public function __construct(array $data = [])
    {
        $this->id = $data['id'] ?? null;
        $this->username = $data['username'] ?? '';
        $this->email = $data['email'] ?? '';
        $this->password = $data['password'] ?? '';
        $this->createdAt = $data['created_at'] ?? null;
    }
    
    public function getId(): ?int
    {
        return $this->id;
    }
    
    public function getUsername(): string
    {
        return $this->username;
    }
    
    public function setUsername(string $username): self
    {
        $this->username = $username;
        return $this;
    }
    
    public function getEmail(): string
    {
        return $this->email;
    }
    
    public function setEmail(string $email): self
    {
        $this->email = $email;
        return $this;
    }
    
    public function setPassword(string $password): self
    {
        $this->password = password_hash($password, PASSWORD_DEFAULT);
        return $this;
    }
    
    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'username' => $this->username,
            'email' => $this->email,
            'password' => $this->password,
            'created_at' => $this->createdAt
        ];
    }
}
        

Menggunakan Repository dalam Controller


namespace App\Controllers;

use App\Models\Repositories\NexaUserRepository;
use App\Models\Domain\UserEntity;
use App\System\NexaController;
use App\System\NexaModel;

class UserController extends NexaController
{
    private $userRepository;
    
    protected function init(): void
    {
        parent::init();
        
        $model = new NexaModel();
        $this->userRepository = new NexaUserRepository($model);
    }
    
    public function profile(int $id): void
    {
        $user = $this->userRepository->findById($id);
        
        if (!$user) {
            $this->redirect('/404');
            return;
        }
        
        $this->assignVars([
            'user' => $user->toArray()
        ]);
        
        $this->render('user/profile');
    }
    
    public function update(): void
    {
        if (!$this->isPost()) {
            $this->redirect('/');
            return;
        }
        
        $id = (int)$this->getPost('id');
        $user = $this->userRepository->findById($id);
        
        if (!$user) {
            $this->setFlash('error', 'User not found');
            $this->redirect('/users');
            return;
        }
        
        $user->setUsername($this->getPost('username'))
             ->setEmail($this->getPost('email'));
        
        if ($this->userRepository->save($user)) {
            $this->setFlash('success', 'User updated successfully');
        } else {
            $this->setFlash('error', 'Failed to update user');
        }
        
        $this->redirect('/users');
    }
}
        

Best Practices

  • Gunakan interface untuk repository untuk memudahkan testing dan dependency injection
  • Pisahkan entity dari model database untuk memastikan domain model tidak tergantung pada implementasi database
  • Gunakan repository untuk semua operasi database, bukan mengakses model langsung dari controller
  • Terapkan validasi di level entity dan model
  • Gunakan dependency injection untuk menginisialisasi repository