- October 21st, 2021
- Code
- By Steve Shead
Creating a car class and extending the database class from the second post.
Updated on November 3rd, 2021 by Steve Shead- October 21st, 2021
- Code
- By Steve Shead
- 0
- 0
Creating a car class and extending the database class from the second post.
This post is a follow up to the second post, creating a website built using OOP, using reusable classes! I decided to see what it would take to extend that site by creating another class - this time around I created a car class.
The picture at the head of this post is the view of the output of the bike class and the car class. As you can see, it turned out quite well. There was some editing to be done for the CRUD pages (create, read, update, delete), and some minor editing in the car class, but it did not take long to put together.
There's a lot more to the website than just the database class, but I am really enamoured with the simplicity of it. To that end, I've posted the database class below.
There's a lot to unpack for this class, but it shows just how it can be reused with a companion class. Take some time to read through it and it will start to make sense.
<?php
class DatabaseObject {
protected static $database;
protected static $table_name = "";
protected static $columns = [];
public $errors = [];
public static function set_database($database) {
self::$database = $database;
}
public static function find_by_sql($sql) {
$result = self::$database->query($sql);
if (!$result) {
exit("Database connection failed");
}
// results into objects
$object_array = [];
while ($record = $result->fetch_assoc()) {
$object_array[] = static::instantiate($record);
}
$result->free();
return $object_array;
}
public static function find_all() {
$sql = "SELECT * FROM " . static::$table_name;
return static::find_by_sql($sql);
}
public static function count_all() {
$sql = "SELECT COUNT(*) FROM " . static::$table_name;
$result_set = self::$database->query($sql);
$row = $result_set->fetch_array();
return array_shift($row);
}
public static function count_by_column($column, $value) {
$sql = "SELECT COUNT(*) FROM " . static::$table_name . " ";
$sql .= "WHERE $column='" . self::$database->escape_string($value) . "'";
$result_set = self::$database->query($sql);
$row = $result_set->fetch_array();
return array_shift($row);
}
public static function find_by_id($id) {
$sql = "SELECT * FROM " . static::$table_name . " ";
$sql .= "WHERE id='" . self::$database->escape_string($id) . "'";
$obj_array = static::find_by_sql($sql);
if (!empty($obj_array)) {
return array_shift($obj_array);
} else {
return false;
}
}
protected static function instantiate($record) {
$object = new static;
foreach ($record as $property => $value) {
if (property_exists($object, $property)) {
$object->$property = $value;
}
}
return $object;
}
protected function validate() {
$this->errors = [];
// Add custom validations
return $this->errors;
}
protected function create() {
$this->validate();
if (!empty($this->errors)) { return false; }
$attributes = $this->sanitized_attributes();
$sql = "INSERT INTO " . static::$table_name . " (";
$sql .= implode(', ', array_keys($attributes));
$sql .= ") VALUES ('";
$sql .= implode("', '", array_values($attributes));
$sql .= "')";
$result = self::$database->query($sql);
if ($result) {
$this->id = self::$database->insert_id;
}
return $result;
}
protected function update() {
$this->validate();
if (!empty($this->errors)) { return false; }
$attributes = $this->sanitized_attributes();
$attribute_pairs = [];
foreach ($attributes as $key => $value) {
$attribute_pairs[] = "{$key}='{$value}'";
}
$sql = "UPDATE " . static::$table_name . " SET ";
$sql .= implode(', ', $attribute_pairs);
$sql .= " WHERE id='" . self::$database->escape_string($this->id) . "' ";
$sql .= "LIMIT 1";
$result = self::$database->query($sql);
return $result;
}
public function save() {
if (isset($this->id)) {
return $this->update();
} else {
return $this->create();
}
}
public function merge_attributes($args) {
foreach ($args as $key => $value) {
if (property_exists($this, $key) && !is_null($value)) {
$this->$key = $value;
}
}
}
public function attributes() {
$attributes = [];
foreach (static::$db_columns as $column) {
if ($column == 'id') { continue; };
$attributes[$column] = $this->$column;
}
return $attributes;
}
protected function sanitized_attributes() {
$sanitized = [];
foreach ($this->attributes() as $key => $value) {
$sanitized[$key] = self::$database->escape_string($value);
}
return $sanitized;
}
public function delete() {
$sql = "DELETE FROM " . static::$table_name . " ";
$sql .= "WHERE id='" . self::$database->escape_string($this->id) . "' ";
$sql .= "LIMIT 1";
$result = self::$database->query($sql);
return $result;
}
// End active record code
}
You saw in the other post what the index page of the dashboard looks like. Below is what the index page of the car class looks like from the dashboard. From this page you can carry out your CRUD operations. It also uses datatables for sorting and pagination. Datatables is my goto plugin for the admin panel in all of my apps.
I know that I've over simplified this, but I wanted to show just how extensible a backend can be when using OOP and adhering to the DRY rule (don't repeat yourself). Creating reusable classes and functions helps keep us from creating spaghetti code and speeds up the build process.
That's it for now. As always, please let me know your thoughts and ideas.
Happy coding!
Cheers
~Steve
Delete Post?
Are you sure you want to delete this post? This action cannot be undone!
Husband, father, grandfather, C Suite leader, engineer, designer, photographer, videographer, musician, composer, pilot, geek, daring to be different - yeah, busy!
All author posts