OOP? Itu makanan ya? Bukan, OOP ini adalah sebuah paradigma pemrograman di mana terdapat objek-objek yang diinisialisasikan dari suatu kelas yang bekerja sebagai cetak biru
Setelah mengetahui ORM terus bisa diapain ya? Nah, bayangkan ketika kita bisa menamai atribut di object pada bahasa pemrograman kita DAN juga dapat menjadi nama kolom di tabel yang kita tentukan. Pasti enak kan? Nah itu kegunaan dari ORM. ORM memungkinkan programer untuk memetakan objek yang berada di logika pemrograman dengan atribut dari sebuah tabel yang biasanya digunakan untuk mengurangi redundansi sebuah proyek kecil sampai menengah.
Pertama-tama, buat proyek dengan direktori
├── assets/
│ ├── css/
│ └── js/
├── config/
├── function/
├── model/
├── create.php
├── edit.php
└── index.php/code>
Selanjutnya download file css dan js bootstrap pada link berikut
CSS Bootstrap JS BootstrapBuat database baru dengan nama pemrograman_web, kemudian buat table mahasiswa sebagai berikut.
CREATE TABLE 'mahasiswa' (
'id' int(11) NOT NULL,
'nim' VARCHAR(16) NOT NULL,
'nama' VARCHAR(128) NOT NULL,
'jurusan' VARCHAR(128) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_cl;
Selanjutnya membuat koneksi ke database, buka file config/Database.php dan ketikan kode program Berkut ini
<?php
class Database
{
private $host = "localhost";
private $username = "root";
private $password = "";
public $conn;
private $db_name = "pemrograman_web";
public function getConnection()
{
$this->conn = null;
try {
$this->conn = new mysqli($this->host, $this->username, $this->password, $this->db_name);
$this->conn->set_charset("utf8");
} catch (Exception $e) {
echo "Connection error: " . $e->getMessage();
}
return $this->conn;
}
}
File Config.php digunakan untuk membuat variable constant yang mana nantinya dapat diakases dari kelas manapun, pada praktikum ini akan membuat variable constant dengan nama BASE_URL yang berisi strng base url dari project yang akan dibuat. Tambahkan kode program berikut pada Config.php
<?php
define('BASE_URL', 'http://localhost/web_programming/lab06/');
Alert.php digunakan untuk membuat sebuah function yang berfungsi untuk menampilkan pesan Ketika melakukan operasi terhadap data, fungsi ini memiliki 2 buah argument statement yaitu $msg yang berisi pesan dan $sts yang berisi kode jika status 1 maka pesan berhasil dan jika 0 maka pesan gagal. Berikut kode program fungsi alert.
<?php function alert($message, $sts)
{
if ($sts == 1) {
$sts = 'success';
} else {
$sts = 'danger';
}
echo '<div class="alert alert-' . $sts . ' alert-dismissible fade show" role="alert">
<strong>' . $message . '</strong>
</div>';
}
Class Mahasiswa digunakan untuk membuat fungsi operasi Create, Read, Update dan Delete data Mahasiswa, berikut ini Langkah-langkah pembuatan class Mahasiswa. Pertama-tama, buat session_start() untuk memulai sesi. Deklarasikan atribut. Buat konstruktor yang mengambil koneksi database. Setelah itu buat fungsi create, read, update, dan delete
<?php
session_start();
class Mahasiswa {
private $conn;
private $table_name = "mahasiswa";
public $id;
public $nim;
public $nama;
public $jurusan;
public function __construct($db) {
$this->conn = $db;
}
public function create() {
$query = "INSERT INTO " . $this->table_name . " SET nim=?, nama=?, jurusan=?";
$stmt = $this->conn->prepare($query);
$stmt->bind_param("sss", $this->nim, $this->nama, $this->jurusan);
if ($stmt->execute()) {
$_SESSION['flash_message'] = "Data berhasil disimpan!";
header("Location: ".BASE_URL."index.php?msg=1");
}else{
$_SESSION['flash_message'] = "Data gagal disimpan!";
header("Location: ".BASE_URL."index.php?msg=0");
}
}
public function read($id="") {
if ($id == "") {
$query = "SELECT * FROM " . $this->table_name;
}else{
$query = "SELECT * FROM " . $this->table_name. " WHERE id= ".$id;
}
$result = $this->conn->query($query);
return $result;
}
public function update() {
$query = "UPDATE " . $this->table_name . " SET nim=?, nama=?, jurusan=? WHERE id=?";
$stmt = $this->conn->prepare($query);
$stmt->bind_param("ssss", $this->nim, $this->nama, $this->jurusan, $this->id);
if ($stmt->execute()) {
$_SESSION['flash_message'] = "Data berhasil diupdate!";
header("Location: ".BASE_URL."index.php?msg=1");
}else{
$_SESSION['flash_message'] = "Data gagal diupdate!";
header("Location: ".BASE_URL."index.php?msg=0");
}
}
public function delete() {
$query = "DELETE FROM " . $this->table_name . " WHERE id=?";
$stmt = $this->conn->prepare($query);
$stmt->bind_param("s", $this->id);
if ($stmt->execute()) {
$_SESSION['flash_message'] = "Data berhasil dihapus!";
header("Location: ".BASE_URL."index.php?msg=1");
}else{
$_SESSION['flash_message'] = "Data gagal dihapus!";
header("Location: ".BASE_URL."index.php?msg=0");
}
}
}
?>
Fungsi mahasiswa ini berfungsi sebagai controller yang menghubungkan antara class/model mahasiswa dengan view, buka file Mahasiswa.php yang berada dalam folder function kemudian tambahkan kode program seperti berikut.Tambahkan file Database.php, Config.php dan model/Mahasiswa.php. Buat object baru Database dan mahasiswa kemudian koneksikan dengan database seperti kode program berikut. Pertama akan dilakukan pengecekan sebuah parameter action yang dikirimkan melalui method GET, jika ada terdapat parameter action yang dikirimkan maka nilai parameter akan diambil dan digunakan sesuai dengan fungsinya, ada 3 buah isi parameter yang dikirimkan yaitu create, delete dan update.
<?php
include_once '../config/Database.php';
include '../config/Config.php';
include_once '../model/Mahasiswa.php';
// Start session if not already started
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
$database = new Database();
$db = $database->getConnection();
$mahasiswa = new Mahasiswa($db);
if (isset($_GET['action'])) {
$action = $_GET['action'];
if ($action == 'create') {
$mahasiswa->nim = $_POST['nim'];
$mahasiswa->nama = $_POST['nama'];
$mahasiswa->jurusan = $_POST['jurusan'];
$mahasiswa->create();
} elseif ($action == 'delete') {
$mahasiswa->id = $_GET['id'];
$mahasiswa->delete();
} elseif ($action == 'update') {
$mahasiswa->id = $_POST['id'];
$mahasiswa->nim = $_POST['nim'];
$mahasiswa->nama = $_POST['nama'];
$mahasiswa->jurusan = $_POST['jurusan'];
$mahasiswa->update();
}
} else {
header("Location: ../index.php?msg=0");
}
View ini berfungsi untuk menampilkan data, menampilkan form input dan update data mahasiswa. File Index.php ini berisi tampilan data-data mahasiswa yag telah berhasil diinputkan kedalam database, berikut ini kode program Index.php
<?php
include './function/Alert.php';
include_once './config/Database.php';
include_once './model/Mahasiswa.php';
$database = new Database();
$db = $database->getConnection();
$mahasiswa = new Mahasiswa($db);
$result = $mahasiswa->read();
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OOP - CRUD</title>
<link href="crud/assets/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-lg-12">
<h4 class="text-center">Data Mahasiswa</h4>
<a class="btn btn-primary btn-sm mb-2" href="create.php">Tambah
Mahasiswa</a>
<!-- show alert -->
<?php
if (isset($_SESSION['flash_message']) && isset($_GET['msg'])) {
if ($_GET['msg'] == '1') {
alert($_SESSION['flash_message'], 1);
} else {
alert($_SESSION['flash_message'], 0);
}
}
?>
<table class="table table-stripped table-bordered">
<thead>
<tr>
<th>#</th>
<th>NIM</th>
<th>NAMA</th>
<th>JURUSAN</th>
<th>ACTION</th>
</tr>
</thead>
<tbody>
<?php $no = 1;
foreach ($result as $row) { ?>
<tr>
<td><?= $no++ ?></td>
<td><?= $row['nim'] ?></td>
<td><?= $row['nama'] ?></td>
<td><?= $row['jurusan'] ?></td>
<td>
<a class="btn btn-success btn-sm"
href="edit.php?id=<?= $row['id'] ?>">Edit</a>
<a class="btn btn-danger btn-sm"
href="crud/function/Mahasiswa.php?action=delete&&id=<?= $row['id'] ?>" onclick="return confirm('Anda yakin ingin menghapus Data <?php echo $row['nama']; ?>?');">Hapus</a>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
<script src="crud/assets/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Setelah itu ada file edit.php yang memodifikasi mahasiswa yang ada.
<?php
include_once 'crud/config/Database.php';
include_once 'crud/model/Mahasiswa.php';
$database = new Database();
$db = $database->getConnection();
$mahasiswa = new Mahasiswa($db);
if (isset($_GET['id'])) {
$result = $mahasiswa->read($_GET['id'])[0];
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OOP - Edit</title>
<link href="./assets/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-
SgOJa3DmI69IUzQ2PVdRZhwQ+dy64/BUtbMJw1MZ8t5HZApcHrRKUc4W0kG879m7"
crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
<h1>Edit Mahasiswa</h1>
<form action="function/Mahasiswa.php?action=update" method="post">
<div class="form-group">
<label for="nim">NIM</label>
<input type="hidden" class="form-control" name="id"
value="<?= $result['id']; ?>" required>
<input type="text" class="form-control" name="nim"
value="<?= $result['nim']; ?>" required>
</div>
<div class="form-group">
<label for="nama">Nama</label>
<input type="text" class="form-control" name="nama"
value="<?= $result['nama']; ?>" required>
</div>
<div class="form-group">
<label for="jurusan">Jurusan</label>
<input type="text" class="form-control" name="jurusan"
value="<?= $result['jurusan']; ?>" required>
</div>
<button type="submit" class="btn btn-primary mt-
2">Update</button>
</form>
</div>
</div>
<script src="./assets/css/bootstrap.min.css" integrity="sha384-
k6d4wzSIapyDyv1kpU366/PK5hCdSbCRGRCMv+eplOQJWyd1fbcAu9OCUj5zNLiq"
crossorigin="anonymous"></script>
</body>
</html>
Database yang diberikan tidak efisien karena bisa membuat beberapa koneksi ke database. Oleh karena itu kita buat hanya satu saja koneksi yang digunakan melalui singleton. Nah diubah kode Database.php menjadi di bawah:
<?php
class Database
{
private $host = "localhost";
private $username = "root";
private $password = "";
public $conn;
private $db_name = "pemrograman_web";
public function getConnection()
{
$this->conn = null;
try {
$this->conn = new mysqli($this->host, $this->username, $this->password, $this->db_name);
$this->conn->set_charset("utf8");
} catch (Exception $e) {
echo "Connection error: " . $e->getMessage();
}
return $this->conn;
}
}
Setelah mempelajari apa itu ORM. Maka kita akan terapkan bagaimana cara menerapkan ORM tersebut. Pertama-tama, kita buat sebuah superclass yang bisa melakukan operasi CRUD dan kita namai "Model".
<?php
include_once './config/Database.php';
abstract class Model
{
protected static string $table; // Database table name
public static function getSorted(string $fieldName, string $order = "ASC")
{
$db = DB::getInstance()->getConnection();
$stmt = $db->prepare("SELECT * FROM " . static::$table . " ORDER BY $fieldName $order");
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($data) {
// Map each record to an object
$objects = array_map([static::class, 'mapToObject'], $data);
return $objects; // Return an array of objects
} else {
return [];
}
}
public static function find(string $fieldName, mixed $value)
{
$db = DB::getInstance()->getConnection();
// Use prepared statements to prevent SQL injection
$stmt = $db->prepare("SELECT * FROM " . static::$table . " WHERE $fieldName = :val");
try {
// Execute the query with the provided value
$stmt->execute(['val' => $value]);
// Fetch the result as an associative array
$data = $stmt->fetch(PDO::FETCH_ASSOC);
// Check if data exists
if ($data === false) {
return null; // Return null if no record is found
}
// Map the result to an object
return static::mapToObject($data);
} catch (PDOException $e) {
// Handle any database errors
error_log("Database error in find(): " . $e->getMessage());
return null;
}
}
public static function find_all(string $fieldName, mixed $value)
{
$db = DB::getInstance()->getConnection();
$stmt = $db->prepare("SELECT * FROM " . static::$table . " WHERE $fieldName = :val");
$stmt->execute(['val' => $value]);
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($stmt);
if ($data) {
// Map each record to an object
$objects = array_map([static::class, 'mapToObject'], $data);
$objects; // Return an array of objects
} else {
return [];
}
}
public static function get_all()
{
$db = DB::getInstance()->getConnection();
$stmt = $db->prepare("SELECT * FROM " . static::$table);
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($data) {
// Map each record to an object
$objects = array_map([static::class, 'mapToObject'], $data);
return $objects; // Return an array of objects
} else {
return null;
}
}
public function save(): bool
{
$db = DB::getInstance()->getConnection();
$fields = get_object_vars($this);
$columns = array_keys($fields);
if (isset($this->id)) {
// Update record
$query = "UPDATE " . static::$table . " SET " . implode(", ", array_map(fn($col) => "$col = :$col", $columns)) . " WHERE id = :id";
} else {
// Insert new record
$query = "INSERT INTO " . static::$table . " (" . implode(", ", $columns) . ") VALUES (" . implode(", ", array_map(fn($col) => ":$col", $columns)) . ")";
}
$stmt = $db->prepare($query);
return $stmt->execute($fields);
}
public function deleteAt(string $fieldName, mixed $value)
{
$db = DB::getInstance()->getConnection();
$stmt = $db->prepare("DELETE FROM " . static::$table . " WHERE $fieldName = :val");
return $stmt->execute(['val' => $value]);
}
private static function mapToObject(array $data): static
{
$object = new static();
foreach ($data as $key => $value) {
$object->$key = $value;
}
return $object;
}
}
Kita jadikan "Model" sebagai superclass dari kelas Mahasiswa kita. Oleh karena itu, seluruh query redundan di create, update, read, dan delete tidak ada lagi. Koneksi ke database ditiadakan karena koneksi bisa dipanggil secara langsung
<?php
session_start();
include_once 'Model.php';
class Mahasiswa extends Model
{
private $conn;
protected static string $table = 'mahasiswa';
public $id;
public $nim;
public $nama;
public $jurusan;
public function create()
{
if ($this->save()) {
$_SESSION['flash_message'] = "Data berhasil disimpan!";
header("Location: " . BASE_URL . "index.php?msg=1");
} else {
$_SESSION['flash_message'] = "Data gagal disimpan!";
header("Location: " . BASE_URL . "index.php?msg=0");
}
return false;
}
public function read($id = "")
{
$res = null;
if ($id == "") {
$res = $this->get_all();
} else {
$res = $this->find("id", $this->id);
}
return $res;
}
public function update()
{
if ($this->save()) {
$_SESSION['flash_message'] = "Data berhasil diupdate!";
header("Location: " . BASE_URL . "index.php?msg=1");
} else {
$_SESSION['flash_message'] = "Data gagal diupdate!";
header("Location: " . BASE_URL . "index.php?msg=0");
}
return false;
}
public function delete()
{
if ($this->deleteAt('id', $this->id)) {
$_SESSION['flash_message'] = "Data berhasil dihapus!";
header("Location: " . BASE_URL . "index.php?msg=1");
} else {
$_SESSION['flash_message'] = "Data gagal dihapus!";
header("Location: " . BASE_URL . "index.php?msg=0");
}
return false;
}
}
Karena constructor model tidak lagi membutuhkan koneksi ke database, kita ubah index.php dan edit.php untuk mengakomodasikan perubahan tersebut.
View index.php
<?php
include './function/Alert.php';
include_once './model/Mahasiswa.php';
$mahasiswa = new Mahasiswa();
$result = $mahasiswa->get_all();
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OOP - CRUD</title>
<link href="./assets/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-lg-12">
<h4 class="text-center">Data Mahasiswa</h4>
<a class="btn btn-primary btn-sm mb-2" href="create.php">Tambah
Mahasiswa</a>
<!-- show alert -->
<?php
if (isset($_SESSION['flash_message']) && isset($_GET['msg'])) {
if ($_GET['msg'] == '1') {
alert($_SESSION['flash_message'], 1);
} else {
alert($_SESSION['flash_message'], 0);
}
}
?>
<table class="table table-stripped table-bordered">
<thead>
<tr>
<th>#</th>
<th>NIM</th>
<th>NAMA</th>
<th>JURUSAN</th>
<th>ACTION</th>
</tr>
</thead>
<tbody>
<?php
$no = 1;
if (!empty($result) && is_array($result)) { // Check if $result is not empty and is an array
foreach ($result as $row) { ?>
<tr>
<td><?= $no++ ?></td>
<td><?= htmlspecialchars($row->nim) ?></td>
<td><?= htmlspecialchars($row->nama) ?></td>
<td><?= htmlspecialchars($row->jurusan) ?></td>
<td>
<a class="btn btn-success btn-sm" href="edit.php?id=<?= htmlspecialchars($row->id) ?>">Edit</a>
<a class="btn btn-danger btn-sm" href="function/Mahasiswa.php?action=delete&&id=<?= htmlspecialchars($row->id) ?>" onclick="return confirm('Anda yakin ingin menghapus Data <?= htmlspecialchars($row->nama) ?>?');">Hapus</a>
</td>
</tr>
<?php }
} else { ?>
<tr>
<td colspan="5" class="text-center">No data available</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
<script src="./assets/js/bootstrap.bundle.min.js"></script>
</body>
</html>
View edit.php
<?php
include_once './model/Mahasiswa.php';
$mahasiswa = new Mahasiswa();
if (isset($_GET['id'])) {
$mahasiswa = Mahasiswa::find('id', $_GET['id']);
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OOP - Edit</title>
<link href="./assets/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-
SgOJa3DmI69IUzQ2PVdRZhwQ+dy64/BUtbMJw1MZ8t5HZApcHrRKUc4W0kG879m7"
crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
<h1>Edit Mahasiswa</h1>
<form action="function/Mahasiswa.php?action=update" method="post">
<div class="form-group">
<label for="nim">NIM</label>
<input type="hidden" class="form-control" name="id"
value="<?= $mahasiswa->id; ?>" required>
<input type="text" class="form-control" name="nim"
value="<?= $mahasiswa->nim; ?>" required>
</div>
<div class="form-group">
<label for="nama">Nama</label>
<input type="text" class="form-control" name="nama"
value="<?= $mahasiswa->nama; ?>" required>
</div>
<div class="form-group">
<label for="jurusan">Jurusan</label>
<input type="text" class="form-control" name="jurusan"
value="<?= $mahasiswa->jurusan; ?>" required>
</div>
<button type="submit" class="btn btn-primary mt-
2">Update</button>
</form>
</div>
</div>
<script src="./assets/css/bootstrap.min.css" integrity="sha384-
k6d4wzSIapyDyv1kpU366/PK5hCdSbCRGRCMv+eplOQJWyd1fbcAu9OCUj5zNLiq"
crossorigin="anonymous"></script>
</body>
</html>
Setelah mengubah view, hal yang juga kita ubah yaitu fungsi mahasiswa.php karena tidak lagi membutuhkan db sebagai konstruktor
<?php
include_once '../config/Database.php';
include '../config/Config.php';
include_once '../model/Mahasiswa.php';
// Start session if not already started
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
$mahasiswa = new Mahasiswa();
if (isset($_GET['action'])) {
$action = $_GET['action'];
if ($action == 'create') {
$mahasiswa->nim = $_POST['nim'];
$mahasiswa->nama = $_POST['nama'];
$mahasiswa->jurusan = $_POST['jurusan'];
$mahasiswa->create();
} elseif ($action == 'delete') {
$mahasiswa->id = $_GET['id'];
$mahasiswa->delete();
} elseif ($action == 'update') {
$mahasiswa->id = $_POST['id'];
$mahasiswa->nim = $_POST['nim'];
$mahasiswa->nama = $_POST['nama'];
$mahasiswa->jurusan = $_POST['jurusan'];
$mahasiswa->update();
}
} else {
header("Location: ../index.php?msg=0");
}
Penerapan konsep OOP dan ORM dapat dengan mudah diterapkan ke proyek dan memiliki manfaat fleksibilitas dan maintainabilitas. OOP memungkinkan kita untuk memiliki standar pemrograman dan ORM memungkinkan kita secara fleksibel mengotak atik properti database tanpa mengubah query. Kedua hal tersebut memiliki manfaat optimalisasi waktu pengembangan yang sangat besar