As a means to try and learn object oriented PHP scripting, I'm currently attempting to rewrite a database web application that I previously wrote in procedural PHP. The application is used to store car parts and information about car parts.
In my application there are car parts. They are identified by various reference numbers, which are assigned by different organisations (the part's manufacturer, re-manufacturers, vehicle manufacturers, etc.), and any particular car part could have zero, one or many reference numbers as assigned by these organisations (and, confusingly, each reference number may refer to more than one unique car part as defined in the database I'm working on).
As far as I understand things, I am dealing with three different classes of entities. There is that of the car part, the reference number, and that of the reference-assigner (in my internal nomenclature I call these 'referrers'). As I am just getting started with learning OOP, I have begun by creating some very basic classes for each:
class Part {
public $part_id;
public $part_type;
public $weight;
public $notes;
public $references;
private $db;
function __construct(Database $db) {
$this->db = $db;
}
}
class Reference {
public $reference_id;
public $reference;
public $referrer;
private $db;
function __construct(Database $db) {
$this->db = $db;
}
}
class Referrer {
public $referrer_id;
public $referrer_name;
private $db;
function __construct(Database $db) {
$this->db = $db;
}
}
?>
What I've been struggling with is how to populate these and subsequently glue them together. The most basic function of my web application is to view a car part, including its metrics and its assigned reference numbers.
A part_id
is included in a page request. Initially, I wrote a constructor method in my Part
class which would look up that part in the database, and then another method which would look up reference numbers (which were JOINed with the referrer table) assigned to that Part ID. It would iterate through the results and create a new object for each reference, and hold the complete set in an array indexed by the reference_id
datum.
After further reading, I began to understand that I should use a factory class to carry this out, however, as this kind of conjunction between my Part
class and my Reference
class is not the responsibility of any one of those discrete classes. This made conceptual sense, and so I have since devised a class that I've called PartReferenceFactory
, which I understand should be responsible for assembling any kind of collation of part reference numbers:
class PartReferenceFactory {
public static function getReferences(Database $db, $part_id) {
$db_result = $db->query(
'SELECT *
FROM `' . REFERRER_TABLE . '`
LEFT JOIN `' . REFERENCE_TABLE . '` USING (`referrer_id`)
INNER JOIN `' . REFERENCE_REL . '` USING (`reference_id`)
WHERE `part_id` = :part_id
ORDER BY `order` ASC, `referrer_name` ASC, `reference` ASC',
array(':part_id' => $part_id);
);
if(empty($db_result)) {
return FALSE;
} else {
$references = array();
foreach($db_result as $reference_id => $reference_properties) {
$references[$reference_id] = new Reference($db);
$references[$reference_id]->reference = $reference_properties['reference'];
$references[$reference_id]->referrer = new Referrer($db);
$references[$reference_id]->referrer->referrer_id = $reference_properties['referrer_id'];
$references[$reference_id]->referrer->referrer_name = $reference_properties['referrer_id'];
}
return $references;
}
}
}
?>
The getReferences method of my factory class is then called inside my Part
class, which I revised thusly:
class Part {
public $part_id;
public $part_type;
public $weight;
public $notes;
public $references;
private $db;
function __construct(Database $db) {
$this->db = $db;
}
function getReferences() {
$this->references = PartReferenceFactory::getReferences($this->db, $this->part_id);
}
}
Really I'm looking for advice on whether my general approach is a good one or if, as I suspect, I've misunderstood something, am overlooking other things, and am tying myself in knots. I will try to distill this into some underlying, directly-answerable questions:
Does my understanding of the purpose of classes and of factory classes seem erroneous?
Is it a bad idea for me to store arrays of objects? I ask from a viewpoint more of design than performance, insofar as they are not intertwined.
Is this even an appropriate way to structure relationships/inter-dependencies between classes in PHP?
Is it correct to call my
PartReferenceFactory
inside thegetReferences
method of the (instantiated)Part
class? And is storing the returned reference objects within the part objects appropriate?As a part of the application's GUI, I'll need to provide lists of referrers, requiring me to create another array of ALL referrers independently of any part object. Yet some of these referrers will exist within the
$references
array inside the part object. It has occurred to me that in order to avoid duplicate referrer objects, I could SELECT a list of all referrers at the beginning of each page request, formulate these into a global array of referrers, and simply reference these from within myPart
andReference
classes as needed. However, I have read that it is not good to rely on the global scope within classes. Is there an elegant/best-practice solution to this?
Thank you very much for the time of whomever happens to read this, and I apologise for the extremely long question. I often worry that I mis-explain matters, and so wanted to be as precise as possible. Please let me know if it would be beneficial for any parts of my post to be deleted.