I have a Laravel project and I'm using Eloquent for models.
Let's say I have three related tables:
User
Demographics
Roles
I would like my User model to inherit both Demographics and Roles based on Foreign Key as a one-to-one relation.
I am just looking for some feedback on what might be the most efficient / elegant / safest / performant / cleanest way to accomplish this.
So you're just looking for basic relations and eager loading those relations.
Try this:
class User extends Model
{
public function demographic()
{
return $this->hasOne('App\Demographic');
}
public function role()
{
return $this->hasOne('App\Role');
}
}
class Demographic extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
}
class Role extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
}
Then to access the User with all relations:
$user = User::with(['demographic', 'role'])->find(1);
var_dump($user->demographic); // returns the related Demographic model
var_dump($user->role); // returns the related Role model
Related
Consider the following world model:
A User can be member of zero or more UserGroups
A UserGroup can have zero or more User members
A Repo can reside in zero or more RepoGroups
A RepoGroup can contain zero or more Repos
A UserGroup can be granted 'read' or 'write' access to a RepoGroup
The (simplified) database schema implementing this model looks like this:
Setting up the Eloquent many-to-many relationship between User and UserGroup via the user_group_pivot table is straight forward, as is the equivalent relationship between Repo and RepoGroup. The access_rights table is a pivot table with additional access information, but the relationship between ClientGroup and RepoGroup is also many-to-many, and equally straight forward. Now the following challenges remain:
The relationship between UserGroup and Repo
The relationship between RepoGroup and User
The relationship between User and Repo
This is the code I've got so far:
class User extends Model {
public function userGroups() {
return $this->belongsToMany(UserGroup::class, 'user_group_pivot');
}
public function repos() {
# Eloquent wizard can makez magic here?
}
public function repoGroups() {
# Eloquent wizard can makez magic here?
}
}
class UserGroup extends Model {
public function users() {
return $this->belongsToMany(User::class, 'user_group_pivot');
}
public function repos() {
# Eloquent wizard can makez magic here?
}
public function repoGroups() {
return $this->belongsToMany(RepoGroup::class, 'access_rights')
->withPivot(['access']);
}
}
class RepoGroup extends Model {
public function repos() {
return $this->belongsToMany(Repo::class, 'repo_group_pivot');
}
public function users() {
# Eloquent wizard can makez magic here?
}
public function userGroups() {
return $this->belongsToMany(UserGroup::class, 'access_rights')
->withPivot(['access']);
}
}
class Repo extends Model {
public function repoGroups() {
return $this->belongsToMany(RepoGroup::class, 'repo_group_pivot');
}
public function repos() {
# Eloquent wizard can makez magic here?
}
public function repoGroups() {
# Eloquent wizard can makez magic here?
}
}
I've scoured the web looking for examples similar to this, but they either blatantly plagiarize the Laravel docs or are equally trivial. I've been playing around with the Model::hasManyThrough() relationship, but to no avail. Hence I put my hopes in the Eloquent wizards of the world. I can haz helps, pliis?
There is a possibility to go to repos without touching other relations.
You can add code like this below to User::repos
$repos = [];
foreach($user->userGroups() as $userGroup){
foreach($userGroup->repoGroups() as $repoGroup){
foreach($repoGroup->repos() as $repo){
$repos[] = $repo;
}
}
If you are worried about performence (example during processing a lot of users) you can use eager loading during fetch users with repos from DB
$users = App\User::with(['userGroups.repoGroups.repos'])->get();
I have Room, Gallery and Images. I want to associate a gallery to the room and then I want to access the Images of the assigned Gallery using the Room model. I'm new into Laravel, I looked in YouTube lessons, and the documentation but didn't found out a solution for my problem.
Room.php:
class Room extends Model
{
protected $table = 'rooms';
public function gallery()
{
return $this->hasOne('App\Gallery');
}
}
Gallery.php:
class Gallery extends Model
{
protected $table = 'gallery';
public function images()
{
return $this->hasMany('App\Image');
}
public function room()
{
return this->belongsTo('App\Room');
}
}
RoomController.php:
$room = Room::findOrFail($id);
$room_gallery = $room->gallery()->images;
return $room_gallery;
With Eloquent relationships, you access them as properties to access the related model(s) or access the method to query or perform additional manipulation.
Since you want a gallery model and it's related image models, you would access the properties of both:
$room_gallery = $room->gallery->images;
With a HasOne, $room->gallery is essentially equal to $room->gallery()->first(). With HasMany, $gallery->images would be essentially equal to $gallery->images()->get().
However, this may be a case where the HasManyThrough relationship would come in handy.
I have a model named Test like this:
class Test extends Model
{
public $primaryKey = 'test_id';
public function questions ()
{
return $this->belongsToMany('App\Question', 'question_test', 'test_id', 'question_id');
}
}
And a Question model like this:
class Question extends Model
{
public function tests ()
{
return $this->belongsToMany('App\Test', 'question_test', 'question_id', 'test_id');
}
}
As you see there is a ManyToMany relation between this two model.
Now in a controller function, I want to get an specific Test(by id) and send it to a view. then eager load all it's questions related models and send it to another view. like this :
public function beginTest ($course_id, $lesson_id, $test_id)
{
$test = Test::find($test_id);
if ($test->onebyone) {
return view('main/pages/test/test-onebyone', compact('test'));
} else {
$test = $test->with('questions.options')->get();
return view('main/pages/test/test-onepage', compact('test', 'done_test_id'));
}
}
}
Problem is that when I use with() laravel method to eager load relations, it return all Test models with their Question relations while I want to get relations of selected Test model only.
what is your solution to solve that?
You can use 'lazy eager loading'.
$test->load('questions.options');
Using with off the model instance will make it use a new builder and cause a new query to be executed.
In the Laravel documentation, there is the following example for retrieving morphedByMany relations, which are many-to-many polymorphic relations.
Laravel Many to Many polymorphic relations documentation
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
/**
* Get all of the posts that are assigned this tag.
*/
public function posts()
{
return $this->morphedByMany('App\Post', 'taggable');
}
/**
* Get all of the videos that are assigned this tag.
*/
public function videos()
{
return $this->morphedByMany('App\Video', 'taggable');
}
}
How would I get a list of all morphed relations in one query / collection, for instance, posts and videos, and then if I later added photos (or anything), that too?
I use a trick here:
Create a Model Taggable for your connection table taggable and add a hasMany relation to the Tag model.
public function related()
{
return $this->hasMany(Taggable::class);
}
Within your Taggable model create a morphedTo relation.
public function taggables()
{
return $this->morphTo();
}
Now you can get all models which are using the tag by calling:
$tagged = Tag::with('related.taggables');
Did you think to use the "union" function of the collections to merge all the different collection in order to retrieve all what you need?
class Tag extends Model
{
[...]
/**
* Get all of.
*/
public function morphed()
{
return $this->video->union($this->posts)->all();
}
}
You should be able to add a relationship on your Tag class as such
public function taggable()
{
return $this->morphedTo();
}
That will use the taggable_id and taggable_type to get the relevant Model that it is tied to.
I'm a real newbie to Laravel but I'm loving it so far. I'm struggling on thing however, I want to retrieve the data for the user that is logged in and I am not sure how to go about this.
I have a few tables but I'll keep it basic for now, I have projects table and a users table, I've defined the relationships between these two in the models as so:
user.php
public function projects() {
return hasMany('project');
}
project.php
<?php
use Illuminate\Database\Eloquent\ModelNotFoundException;
class Project extends Eloquent
{
public function user()
{
return belongsTo('user');
}
}
I know I can do the following to retrieve all projects in the database with a foreach loop, however this doesn't retrieve the logged in users projects:
$projects = DB::table('projects')->get();
I saw one tutorial which wasn't very in depth but he said to access the model query I would have to use the following command:
$project = User::all()->projects;
However this hasn't worked either. Can anyone point me into the right direction with real tutorials or post simple examples?
Thanks in advance
Those are the projects of your logged in user:
if (Auth::check())
{
$projects = Auth::user()->projects;
}
And this must be in your relation:
class User extends Eloquent
{
public function projects() {
return this->hasMany('Project');
}
}
You also need to add $this to your Project relation:
class Project extends Eloquent
{
public function user()
{
return $this->belongsTo('User');
}
}