Skip to content

New Mapper Query Syntax Proposal

vlucas edited this page Feb 7, 2012 · 3 revisions

Currently, it is a little awkward to have and use/switch to a custom Mapper instance instead of the global "generic" one if you want to run custom queries. So this is a proposal to modify the query syntax a bit so that using and providing custom mappers is easy and seamless.

Current Syntax

Currently, a new Mapper must be manually instantiated, which forces developers to expose the config object in order to manually construct new mappers when required.

$postMapper => new Post\Mapper($cfg); // Custom Mapper
$posts = $postMapper->all('Post\Entity');

The major drawback to the approach is that normal queries can still be run on the Entity without going through the custom Mapper, which could result in unexpected behavior in some circumstances.

$mapper => new Spot\Mapper($cfg); // Default Mapper 
$posts = $mapper->all('Post\Entity'); // Normal queries still work, but without behavior from custom `all` method

Suggested New Syntax

The suggested new syntax has a few aspects to it:

  • Add a new public instance method on Spot\Mapper called entity that will take the name of an Entity object to use for queries
  • Remove the Entity name from first parameter of Mapper query methods like all and find (breaking backwards compatibility)
  • Add new public static method on Spot\Entity called mapper that accepts the current Spot\Config object and returns a custom mapper instance to use that will be returned by the Spot\Mapper entity method

The new syntax would look like this:

// Default Spot Mapper still  
$mapper => new Spot\Mapper($cfg);  
$posts = $mapper->entity('Post\Entity')->all();  

Entity and Mapper class definitions with new method to specify Mapper from Entity

namespace Post;

// Entity
class Entity extends Spot\Entity
{
  // If method exists and returns a mapper instance, use that mapper
  public static function mapper($cfg)
  {
    $mapperClass = __NAMESPACE__ . '\Mapper';
    return new $mapperClass($cfg);
  }
}


// Custom Mapper
class Mapper extends Spot\Mapper
{
  public function all()
  {
    // custom behavior that will now always get used...
  }
}

This elegantly solves the Mapper issue while simultaneously reducing syntax clutter in the main finder methods and allows Entity-based configuration and Mapper modifications (like an Entity that uses MongoDB as the primary connection from the passed config instead of the default).