Access all of Typerocket. Get Pro.
Relationships
( v5 )
- # ORM Model Relationships
- # One to One
- # Implementation
- # One To Many
- # Implementation
- # Many to Many
- # Implementation
- # Saving Many to Many Relationships
- # Saving Data To Pivot Table
- # Taxonomy Relationships
- # Scoping Relationships
- # Querying Relationship Existence
ORM Model Relationships
Model relationships define how records are related in the database. The main relationship types include: "one to one", "one to many", and "many to many".
One to One
In a one to one relationship, one record can have only one reference to another record and vice-versa. For example, one Seat can have one Person if you are booking a plane flight.
Implementation
Take the plane flight example where one Person has one Seat. For the Person model, let's assume there is a table named wp_people with the columns id, name, and email. For the Seat model lets assume there is a table named wp_seats with the columns id, person_id, seat_number, and price. How would you represent the database relationship in your TypeRocket models?
Take a look at the Person model.
<?php
namespace App\Models;
use \TypeRocket\Models\Model;
class Person extends Model
{
protected $resource = 'people';
/**
* Get the seat record associated with the person.
*/
public function seat()
{
return $this->hasOne('\App\Models\Seat', 'person_id');
}
}
And, look at the Seat model.
<?php
namespace App\Models;
use \TypeRocket\Models\Model;
class Seat extends Model
{
protected $resource = 'seats';
/**
* Get the person record associated with the seat.
*/
public function person()
{
return $this->belongsTo('\App\Models\Person', 'person_id');
}
}
Now, you can access the Seat from the Person using the seat() method. Take a look at the example where $person is an instance of Person.
$seat = $person->findById(1)->seat()->get();
You can also access the Person in a Seat. Take a look at the example where $seat is an instance of Seat.
$seat = $seat->findById(1)->person()->get();
One To Many
In one to many relationships, one record can have many other related records. For example, one Game can have many a Player in a video game.
Implementation
Take the video game example where one Game and have many a Player. For the Game model, let's assume there is a table named wp_games with the columns id and name. For the Player model, let's assume there is a table named wp_players with the columns id, games_id and name. How would you represent the database relationship in your TypeRocket models?
Take a look at the Game model.
<?php
namespace App\Models;
use \TypeRocket\Models\Model;
class Game extends Model
{
protected $resource = 'games';
/**
* Get the player records associated with the game.
*/
public function players()
{
return $this->hasMany('\App\Models\Player', 'games_id');
}
}
And, look at the Player model.
<?php
namespace App\Models;
use \TypeRocket\Models\Model;
class Player extends Model
{
protected $resource = 'players';
/**
* Get the game record associated with the player.
*/
public function game()
{
return $this->belongsTo('\App\Models\Game', 'games_id');
}
}
Now, you can access the Player records from the Game using the players() method. Take a look at the example where $game is an instance of Game.
$players = $game->findById(1)->players()->get();
You can also access the Game from a Player. Take a look at the example where $player is an instance of Player.
$game = $player->findById(1)->game()->get();
Many to Many
In many to many relationships, many records can have many other related records. For example, many an Author can have many a Book and vice-versa in a bookstore.
Implementation
Many to many relationships are a more complicated topic. For brevity, just remember that many to many relationships require a "junction table". A junction table stores the relationship associations as records.
Take the bookstore example. For the junction table lets assume it is named wp_authors_books with the columns authors_id and books_id. For the Author model, let's assume there is a table named wp_authors with the columns id and name. For the Book model, let's assume there is a table named wp_books with the columns id, title, price and pages. How would you represent the database relationship in your TypeRocket models?
Take a look at the Author model.
<?php
namespace App\Models;
use \TypeRocket\Models\Model;
class Author extends Model
{
protected $resource = 'authors';
/**
* Get the player records associated with the game.
*/
public function books()
{
$model = '\App\Models\Book';
$table = 'wp_authors_books';
return $this->belongsToMany($model, $table, 'books_id', 'authors_id');
}
}
And, look at the Book model.
<?php
namespace App\Models;
use \TypeRocket\Models\Model;
class Book extends Model
{
protected $resource = 'books';
/**
* Get the player records associated with the game.
*/
public function authors()
{
$model = '\App\Models\Author';
$table = 'wp_authors_books';
return $this->belongsToMany($model, $table, 'authors_id', 'books_id');
}
}
Now, you can access the Book records of the Author using the books() method. Take a look at the example where $author is an instance of Author.
$authors_books = $author->findById(1)->books()->get();
Now, you can access the Author records of the Book using the authors() method. Take a look at the example where $book is an instance of Book.
$books_authors = $book->findById(1)->authors()->get();
Saving Many to Many Relationships
To save the relationship of a Book to an Author use the attach() method. For example, if you have author records with the IDs 1, 2, and 3 you can attach them to a book as follows.
$book->findById(1)->authors()->attach([1,2,3]);
You can also detach author records with the detach() method.
$book->findById(1)->authors()->detach([4,5,6]);
If you want to have only a specific set or records applied then you would need to detach all records and then attach the records you want.
$books_authors = $book->findById(1)->authors();
$books_authors->detach();
$books_authors->attach([1,2,3]);
Or, you can use the shortcut method sync() to detach all authors and then attach the desired authors.
$book->findById(1)->authors()->sync([1,2,3]);
Saving Data To Pivot Table
To attach extra data to a pivot table row, pass an array to the attach method.
$date = date('Y-m-d H:i:s');
$books_authors = $book->findById(1)->authors();
// attach author to book with pivot table data
$books_authors->attach([
[1, 'units' => '12', 'created_at' => $date],
[2, 'units' => '4', 'created_at' => $date],
[3, 'units' => '2', 'created_at' => $date],
]);
Taxonomy Relationships
If you have a custom post type model with custom taxonomies, you can define the relationship using the belongsToTaxonomy() method.
<?php
namespace App\Models;
use TypeRocket\Models\WPPost;
class Post extends WPPost
{
protected $postType = 'post';
public function categories()
{
return $this->belongsToTaxonomy(Category::class, 'category');
}
public function tags()
{
return $this->belongsToTaxonomy(Tag::class, 'post_tag');
}
}
Scoping Relationships
You can scope any inner relationship as well by passing a callback.
<?php
use TypeRocket\Models\Model;
class ExampleModel extends Model
{
public function publishedBlog()
{
$model = '\App\Models\Blog';
return $this->hasOne($model, 'blog_id', function($rel) {
// only blogs that are published
$rel->where('status', 'publish');
});
}
public function takenSeat()
{
$model = '\App\Models\Seat';
return $this->belongsTo($model, 'seat_id', function($rel) {
// only a seat that is taken
$rel->where('status', 'taken');
});
}
public function fromFirstThousandBooks()
{
$model = '\App\Models\Book';
$table = 'wp_authors_books';
return $this->belongsToMany($model, $table, 'books_id', 'authors_id', function($rel) {
// Scopes wp_authors_books model/query
$rel->where('books_id', '<', 1000);
});
}
public function tags()
{
$model = '\App\Models\Tag';
return $this->belongsToTaxonomy($model, 'post_tag', function($rel) {
// Scopes term_relationships model/query
$rel->where('books_id', '<', 1000);
});
}
}
Querying Relationship Existence
When retrieving model records, you can limit your results based on the existence of a relationship. To do so, you may pass the name of the relationship to the has() and hasNo() methods:
ExampleModel::new()->has('tags')->get();
ExampleModel::new()->hasNo('tags')->get();
You can also scope and nest existence queries:
use \App\Models\Blog;
use \App\Models\Post;
ExampleModel::new()->has('publishedBlog', function(Blog $query) {
$query->has('posts', function(Post $query) {
$table = $query->getTable();
$query->where("{$table}.post_status", 'draft');
});
})->get();
Further, you can define the existence where condition as OR:
ExampleModel::new()
->where('name', 'kevin')
->has('tags', null, 'OR')
->get();
Found a typo? Something is wrong in this documentation? Fork and edit it!