Yes I think your components are mis-labelled. Take a look at my sig link for an ex. of what a basic datamapper functionality does
A repository would be an object you could instantiate and use something like:
Code: Select all
$repo = new Repo();
$repo->addCriteria( Critera_Username::eq( 'foo' );
$domainModels = $repo->getFiltered();
Internally the repo would use a query object, and submit that to the data mapper
Although, this is overkill IMO. My workflow is to create a mapper for each logical entity, and create specialized finders. Later on I can send a database guy 50 or so mappers and have him rewrite the schema or query strategy
so I can just do $user = $dataMapper->useSpecialFindByUsernameMethod( 'foo' )
Sometimes I build these little simplistic query objects specific to 1 domain only each. Maybe someday I'll build more of a framework for that. This is useful when there would be too many finders,
like finding messages unread but archived
finding read by unarchived
finding read and in inbox
finding read and in sent
finding unreading in inbox
finding unread in sent
etc...
( you don't want to hard code finders in this case. This is where Repository & Query object pattern makes sense)
For example I avoided what I feel is a lot of complex code by using this little helper inside of my mapper:
Code: Select all
<?php
class Message_Mapper_Filter
{
public function notDraftNotTrash()
{
return '`draft` = 0 && `trash` = 0';
}
public function draftAndNotTrash()
{
return '`draft` = 1 && `trash` = 0';
}
public function unarchived()
{
return $this->notDraftNotTrash() . ' && `archived` = 0';
}
public function archived()
{
return $this->notDraftNotTrash() . ' && `archived` = 1';
}
public function unread()
{
return $this->unarchived() . ' && `read` = 0';
}
public function inbox( User $user )
{
return $this->unarchived() . ' && `recipient_id` = ' . (int)$user->getId();
}
public function sent( User $user )
{
return $this->unarchived() . ' && `sender_id` = ' . (int)$user->getId();
}
public function all( User $user )
{
$id = (int)$user->getId();
return $this->notDraftNotTrash() . ' && ( `sender_id` = ' . $id . ' || `recipient_id` = ' . $id . ')';
}
public function sender( User $user )
{
return '`sender_id` = ' . $user->getId();
}
public function trash( User $user )
{
$id = (int)$user->getId();
return '`trash` = 1 && ( `sender_id` = ' . $id . ' || `recipient_id` = ' . $id . ')';
}
}
Then I use these basic building blocks to create a lot of finders on the fly that end up looking like:
Code: Select all
/**
* List archived messages for a given user
*
* @param User the user to list the archived messages for
* @return Shuffler_Collection collection of Message objects
*/
public function listArchived( User $user, $offset = NULL, $limit = NULL )
{
return $this->listWhere( $this->filter->archived() . ' && ' . $this->filter->sender( $user ), $offset, $limit );
}
I think the most important thing you can do is unit test your mappers, honestly. For this you need to be using innoDb to do it right! You should test a full save & a full read!