I think the thing you are missing is the desire to understand how existing software works. Doctrine 2 stores mapping information in a manager class. The manager class in turn acts as a repository factory. Not sure how you get service locator and static functions from this.
Take it for a test drive so you know how it works instead of guessing.
It’s an implementation detail and there are many solutions. In Maphper I solved this by having each mapper attach child mappers to the entities dynamically so:
$authorSource = new \Maphper\DataSource\Database($pdo, 'author', 'id');
$authors = new \Maphper\Maphper($authorSource);
$blogSource = new \Maphper\DataSource\Database($pdo, 'blog', 'id');
$blogs = new \Maphper\Maphper($blogSource);
$relation = new \Maphper\Relation\Many($blogs, 'id', 'authorId');
$authors->addRelation('blogs', $relation);
$relation = new \Maphper\Relation\One($authors, 'authorId', 'id');
$blogs->addRelation('author', $relation);
And once it’s set up, it’s managed internally and transparently so you can call:
foreach ($author->blogs as $blog) {
}
//or
echo $blog->author->name;
And it just works without needing to inject extra dependencies. Imho this is the cleanest way of doing it because none of the dependencies of the mappers are known outside the top level where they’re configured.