Skip to content
Richard edited this page Jun 16, 2016 · 1 revision

Relationships

If there was an author table which stored information about blog authors, it could be set up in a similar way:

$authorSource = new \Maphper\DataSource\Database($pdo, 'author', 'id');
$authors = new \Maphper\Maphper($authorSource);

This could be used similarly:

$author = $authors[123];
echo $author->name;

Once both the blogs and authors mappers have been defined, you can create a relationship between them.

This is a one-to-one relationship (one blog has one author) and can be achieved using the addRelation method on the blog mapper:

//Create a one-to-one relationship between blogs and authors (a blog can only have one author)
$relation = new \Maphper\Relation\One($authors, 'authorId', 'id');
$blogs->addRelation('author', $relation);

Using an instance of \Maphper\Relation\One tells Maphper that it's a one-to-one relationship

The first parameter, $authors tells Maphper that the relationship is to the $authors mapper (in this case, the author database table, although you can define relationships between different data sources)

authorId is the field in the blog table that's being joined from

id is the field in the author table that's being joined to

After the relation is constructed it can be added to the blog mapper using:

$blogs->addRelation('author', $relation);

The first parameter (here: 'author') is the name of the property the related data will be available under. So any object retrieved from the $blogs mapper will now have an 'author' property that contains the author of the blog and can be used like this:

foreach ($blogs as $blog) {
  echo $blog->title . '<br />';
  echo $blog->author->name . '<br />';
}

Similarly, you can define the inverse relation between authors and blogs. This is a one-to-many relationship because an author can post more than one blog.

//Create a one-to-many relationship between blogs and authors (an author can have multiple blog entries)
//Joining from the 'id' field in the authors mapper to the 'authorId' field in the blogs mapper
$relation = new \Maphper\Relation\Many($blogs, 'id', 'authorId');
$authors->addRelation('blogs', $relation);

This is creating a One:Many relationship between the $authors and $blogs mappers using the id field in the $authors mapper to the authorId field in the $blogs mapper and making a blogs property available for any object returned by the $authors mapper.

//Count all the blogs by the author with id 4
$authors[4]->name . ' has posted ' .  count($authors[4]->blogs)  . ' blogs:<br />';

//Loop through all the blogs created by the author with id 4
foreach ($authors[4]->blogs as $blog) {
    echo $blog->title . '<br />';
}

Saving values with relationships

Once you have created your mappers and defined the relationships between them, you can write data using the relationship. This will automatically set any related fileds behind the scenes.

$authors = new \Maphper\Maphper(new \Maphper\DataSource\Database($pdo, 'author'));
$blogs = new \Maphper\Maphper(new \Maphper\DataSource\Database($pdo, 'blog', 'id'));
$blogs->addRelation('author', new \Maphper\Relation\One($authors, 'authorId', 'id'));


$blog = new stdClass;
$blog->title = 'My First Blog';
$blog->date = new \DateTime();
$blog->author = new stdClass;
$blog->author->name = 'Tom Butler';

$blogs[] = $blog;

This will save both the $blog object into the blog table and the $author object into the author table as well as setting the blog record's authorId column to the id that was generated.

You can also do the same with one-to-many relationships:

$authors = new \Maphper\Maphper(new \Maphper\DataSource\Database($pdo, 'author'));
$blogs = new \Maphper\Maphper(new \Maphper\DataSource\Database($pdo, 'blog', 'id'))

$authors->addRelation('blogs', new \Maphper\Relation\Many($blogs, 'id', 'authorId'));


//Find the author with id 4
$author = $authors[4]; 


$blog = new stdClass;
$blog->title = 'My New Blog';
$blog->date = new \DateTime();

//Add the blog to the author. This will save to the database at the this point, you do not need to explicitly 
//Save the $author object after adding a blog to it.
$author->blogs[] = $blog;