So Composition over Inheritance would be something like this
<?php
// ErrorHandler.php
namespace PhotoTech;
use Exception;
use PDOException;
class ErrorHandler
{
public function handlePDOException(PDOException $e): void
{
error_log('PDO Error: ' . $e->getMessage());
echo 'An error occurred while connecting to the database.';
}
public function handleGeneralException(Exception $e): void
{
error_log('General Error: ' . $e->getMessage());
echo 'An error occurred.';
}
}
and the Database Class
<?php
// Database.php
namespace PhotoTech;
use Exception;
use PDO;
use PDOException;
class Database
{
private ErrorHandler $errorHandler;
public function __construct(ErrorHandler $errorHandler)
{
$this->errorHandler = $errorHandler;
}
public function createPDO(): ?PDO
{
try {
$db_options = [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
];
return new PDO('mysql:host=' . DATABASE_HOST . ';dbname=' . DATABASE_NAME . ';charset=utf8mb4', DATABASE_USERNAME, DATABASE_PASSWORD, $db_options);
} catch (PDOException $e) {
$this->errorHandler->handlePDOException($e);
return null;
} catch (Exception $e) {
$this->errorHandler->handleGeneralException($e);
return null;
}
}
}
So the Database
class contains an instance of the ErrorHandler
class as a private property, which it can use to delegate error handling to the ErrorHandler
instance using its public methods. This approach provides more flexibility and decoupling between classes. So if I wanted to I could use a different or better error handler?
So I am trying to simplify things and I got away from using static variables and methods and came up with this →
<?php /** @noinspection ALL */
namespace PhotoTech;
use Exception;
use JetBrains\PhpStorm\Pure;
use DateTime;
use DateTimeZone;
use PDO;
class CMS
{
protected string $table = "cms"; // Table Name:
protected array $db_columns = ['id', 'category', 'user_id', 'thumb_path', 'image_path', 'Model', 'ExposureTime', 'Aperture', 'ISO', 'FocalLength', 'author', 'heading', 'content', 'data_updated', 'date_added'];
public $id;
public $user_id;
public $page;
public $category;
public $thumb_path;
public $image_path;
public $Model;
public $ExposureTime;
public $Aperture;
public $ISO;
public $FocalLength;
public $author;
public $heading;
public $content;
public $date_updated;
public $date_added;
protected PDO $pdo;
/*
* Construct the data for the CMS
*/
public function __construct(PDO $pdo, array $args = [])
{
$this->pdo = $pdo;
// Caution: allows private/protected properties to be set
foreach ($args as $k => $v) {
if (property_exists($this, $k)) {
$v = $this->filterwords($v);
$this->$k = $v;
$this->params[$k] = $v;
$this->objects[] = $v;
}
}
} // End of construct method:
/*
* Create a short description of content and place a link button that I call 'more' at the end of the
* shorten content.
*/
#[Pure] public function intro($content = "", $count = 100): string
{
return substr($content, 0, $count) . "...";
}
public function setImagePath($image_path) {
$this->image_path = $image_path;
}
public function countAllPage($category = 'home')
{
$sql = "SELECT count(id) FROM " . $this->table . " WHERE category=:category";
$stmt = $this->pdo->prepare($sql);
$stmt->execute(['category' => $category ]);
return $stmt->fetchColumn();
}
public function page($perPage, $offset, $page = "index", $category = "home"): array
{
$sql = 'SELECT * FROM ' . $this->table . ' WHERE page =:page AND category =:category ORDER BY id DESC, date_added DESC LIMIT :perPage OFFSET :blogOffset';
$stmt = $this->pdo->prepare($sql); // Prepare the query:
$stmt->execute(['page' => $page, 'perPage' => $perPage, 'category' => $category, 'blogOffset' => $offset]); // Execute the query with the supplied data:
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
protected function filterwords($text) {
$filterWords = array('Gosh Darn It');
$filterCount = sizeof($filterWords);
for ($i = 0; $i < $filterCount; $i++) {
$text = preg_replace_callback('/\b' . $filterWords[$i] . '\b/i', function($matches){return str_repeat('*', strlen($matches[0]));}, $text);
}
return $text;
}
} // End of class:
The only thing now I am kind of confused about is error handling but I will figure it out.
Found this statement about Composition over Inheritance
that explains it pretty good for me I think →
“Composition over Inheritance” is a software development principle that recommends the use of object composition rather than class inheritance to achieve code reuse and modular design. In PHP, it means that instead of creating a subclass that inherits from a base class, you create a new class that contains an instance of the base class as a property and delegates calls to that instance.
And I’m just starting to understand the approach of polymorphism and how an interface allows for more flexibility and extensible code.
Thanks for the help.