
Originally Posted by
Grnadpa
And I wonder if this approach doesn't overly bind these dbManagers too tightly to the implementors. Yes, lesson_horse_Form is the primary CRUD engine for the horse table (as are the corresponding lessons_student and lesson_tack for their respective tables).
BUT there is also an 'alesson' table whose form builds drop-down lists from all three student, horse and tack (using the functions GetStudentList, GetHorseList and GetTackList respectively) to assure that only valid values are available on the user's form.
In this EXTENDS scenario, then, I see four mySQL connections in my lesson form -- which makes passing the connection as an argument to the implementor (if I'm using the term correctly) appear to be a preferred approach. Or do we forego encapsulation and throw all four tables into one dbManager for the alesson form?
TO DIGRESS / RANT: I'm having a hard time understanding how replacing Mysql with either PDO or Mysqli represents anything but overkill for a low-activity user-conversational application like this one. In fact, what kind of application requires the high volume that these Mysql replacements are meant to make more efficient -- where, say, Java isn't a better language choice?
Okay, maybe the naming convention led me down the path of extends, let's rename them and look at Dependency Injection.
Your lessons_template_dbManager doesn't change
PHP Code:
<?php
Class lessons_template_dbManager {
Protected $dbManager = null;
Protected $trace = false;
public function getDbManager()
{
return $this->dbManager;
}
Public Function __Construct() { // assure connection
if($this->trace) {
echo("<br />lessons_template_dbmanager->Construct");
}
if(isset($this->dbManager)) {
if($this->trace) {
echo("<br />lessons_template_dbmanager->db is set");
}
return true;
}
if($this->trace) {
echo("<br />lessons_template_db->dbmanager is NOT set");
}
$currentHost = pathinfo($_SERVER['REMOTE_ADDR'],PATHINFO_BASENAME);
if($currentHost == "127.0.0.1"){ // no place like home
$theUsername = "root";
$thePassword = "";
} else {
//--> detail omitted <--
}
try {
$this->dbManager = new PDO('mysql:host=localhost;dbname=lessons;charset=UTF-8', $theUsername, $thePassword);
$this->dbManager->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->dbManager->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $ex) {
echo("<p style='font-weight: bold; color: red; font-size: larger;'><br /><br /><br />A serious error occurred, contact programmer who will need the following detail<br /></p>");
echo("<br />lessons_template_dbManager->Construct<br />");
var_dump($ex);
exit();
}
} // end function
} // end class
?>
Your lessons_horse_dbManager becomes lessons_horse_repository
PHP Code:
<?php
Class lessons_horse_repository {
protected $dbManager = null;
protected $trace = true;
Public Function __Construct($dbManager) {
if($this->trace) {
echo("<br />lessons_horse_repository->__Construct");
}
$this->dbManager = $dbManager;
}
Public Function GetHorseList() {
if($this->trace) {
echo("<br />lessons_horse_repository->GetHorseList");
}
// dispensing with try-catch
$stmt = $this->dbManager->prepare("SELECT name FROM horses ORDER BY name");
$stmt->execute();
$nameList = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$nameList[] = $row['name'];
} // end while
return($nameList);
} // end function
//...
// Create, Update, Delete functions should also exist
}
?>
Your lessons_horse_Form
PHP Code:
<?php
Class lessons_horse_Form
extends lessons_template_Base{
// If you don't have any other setup, delete this construct function,
// as it will then invoke the parent automatically
public function __construct($dbManager)
{
parent::__construct($dbManager);
}
//...other functions...
Function BuildContent(){
//...
$horseObj = new lessons_horse_repository($this->dbManager);
$horseValues = $horseObj->GetHorseList();
//...
}
}
Your lessons_template_Base
PHP Code:
<?php
class lessons_template_Base
{
protected $dbManager = null;
public function __construct($dbManager)
{
$this->dbManager = $dbManager;
}
//... any shared functions across students, horses, and track
}
Implementation
PHP Code:
<?php
$dbManager = new lessons_template_dbManager();
$horseForm = new lessons_horse_Form($dbManager->getDbManager());
$horseForm->BuildContent();
One thing to note. I am passing $dbManager->getDbManager() so the all of the DIs have the same implementation (granted there are two ways to do this). The above, which passes in the getDbManager(), OR each Form/Repository class would have to utilize $this->dbManager->getDbManager()->prepare... for each call.
Why not just pass in $dbManager and then in the construct set the protected $dbManager to getDbManager()? Good question, let's follow that path
- lessons_horse_Form will receive it and set its' internal $dbManager to the result of getDbManager()
- now it passes its' internal $dbManager to lessons_horse_repository (which is the result of getDbManager())
- the construct for the repository now doesn't need to call getDbManager(), giving it a different implementation
Really isn't a big deal, but I like to keep my underlying implementations the same, though I will accept the argument that the *_Form classes would have the same implementation of using getDbManager() and the *_repository classes would have the same implementation of not having to call getDbManager().

Originally Posted by
guido2004
Yes. To have the parent's construct to execute, you must not have a contruct in the child class, or explicitely call the parent's construct:
PHP Code:
Public Function __Construct() {
if($this->trace) {
echo("<br />lessons_horse_dbManager->__Construct");
}
parent::__construct();
}
Yep, I missed that one, but I caught the form one Thanks for the assist @guido2004 ;
Bookmarks