PHP Datamapper with multiple objects
<p>Okay, so I have a problem. I've been using sort of a datamapper-approach to load my objects. I'm really new to this kind of approach (and OO in general), so issues arise from time to time. So far my scenarios have been relatively simple. For example, I have a database table which contains products. Products have fields such as name, code, description, product group (actually a reference to another table) and so on. Product class is loaded and initialized with ProductMapper which queries the products and productgroups tables and returns the object.</p>

<pre><code>Class Product
{
    private $id;
    private $code;

    ...

    public function __construct($id){
        $this-&gt;id = $id;
    }

    public function getName(){
        return $this-&gt;name;
    }

    ...
}


Class ProductMapper
{
    private $db;

    public function __construct (PDO $db){
        $this-&gt;db = $db;
    }

    public function find($id){
        $sql = $this-&gt;db-&gt;prepare("SELECT p.ID, p.Name, p.Code, p.Price, p.Description, p.ProductGroup, p.ProductGroupName, p.PackageSize 
        FROM products p
        INNER JOIN productgroups g ON p.ProductGroupID = g.ID 
        WHERE p.ID = :id");

        $sql-&gt;bindValue(':id',$id, PDO::PARAM_INT);
        $sql-&gt;execute();
        $productResult = $sql-&gt;fetchAll(PDO::FETCH_ASSOC);
        if(count($productResult) == 1){

            $product = new Product($id);
            $product-&gt;setName($result[0]['Name']);

            ...

            return $product;
        }
    }
}
</code></pre>

<p>So far everything works for me. The problem I'm having with this approach is that what if I want (and I really want) to create a class and a mapper for ProductGroup. My plan is to replace ProductGroupID in Product class with actual ProductGroup object. </p>

<p>I've come up with few scenarios to make this happen:</p>

<p>1: Create a ProductGroupMapper inside ProductMapper class:</p>

<pre><code>Class ProductMapper
{
    private $db;
    private $groupMapper;

    public function __construct (PDO $db){
        $this-&gt;db = $db;
        $this-&gt;groupMapper = new ProductGroupMapper($db);
    }

    ...
}
</code></pre>

<p>2: Create product and productgroup as separate objects:</p>

<pre><code>$product = $productMapper-&gt;find(1);
$group = $productGroupMapper-&gt;find($product-&gt;getGroupID());
$product-&gt;setGroup($group);
</code></pre>

<p>3: Pass ProductGroup mapper as a dependency for the ProductMapper:</p>

<pre><code>Class ProductMapper
{
    private $db;
    private $groupMapper;

    public function __construct (PDO $db, ProductGroupMapper $pgMapper){
        $this-&gt;db = $db;
        $this-&gt;groupMapper = $pgMapper;
    }

    ...
}
</code></pre>

<p>First option creates a very tight coupling between the two mappers and this creeps me out. Second option is probably more flexible, but creates a lot of extra code and is prone to mistakes. I like the third option best, but I still have concerns that I might be painting myself into a corner... As for creating mappers, I was thinking about creating somekind of a factory class which would create the correct mapper and inject the necessary dependecies.</p>

<p>Or am I just making a huge mess?</p>