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.
Related
I built a one to one relationship between two Eloquent models and I want to replace an relationship attribute called profile_picture inside my User Eloquent model but I don't know how to do it.
This is a summary of my User model.
class User extends Authenticatable implements JWTSubject{
use Notifiable;
public function profile_picture(){
return $this->hasOne(UserProfilePicture::class);
}
}
And this is a summary of my UserProfilePicture model.
class UserProfilePicture extends Model{
public function user(){
return $this->belongsTo(User::class);
}
}
This is how I pretent to do it in my UserController file.
public function publicUserData($username){
$user = User::where("username", $username)->with("profile_picture")->first();
if($user){
if(!$user->profile_picture){
$user->profile_picture = UserProfilePicture::$defaultUserProfilePicture;
}
return response()->json($user);
}
return response()->json(false);
}
This is $defaultUserProfilePicture static array.
public static $defaultUserProfilePicture = [
"url" => "public/avatars/defaultUserPhoto.jpg",
"size" => 5229
];
I tried to use mutators but looks like it isn't work on relationships attributes.
I found this but doesn't work for me.
Thanks in advance.
You can provides the relation default model with attributes, you may pass an array or Closure to the withDefault method
public function profile_picture(){
return $this->hasOne(UserProfilePicture::class)->withDefault(UserProfilePicture::$defaultUserProfilePicture);
}
Reference: https://laravel.com/docs/7.x/eloquent-relationships#default-models
I solved it, first I put the static array UserProfilePicture::$defaultUserProfilePicture into my database then I do:
$user->setRelation("profile_picture", UserProfilePicture::find(1));
That take one more database request but is the one solution to I have for now.
Let's consider the Einstein's Puzzle and these two models:
class Pet extends Eloquent
{
public function pet()
{
return hasOne(Man::class)
}
}
class Man extends Eloquent
{
public function pet()
{
return belongsTo(Pet::class)
}
}
If I want to get all the Pets:
Pet::all()->toArray();
I'll get for instance:
{
id: 2,
man: {
nationality: "German",
pet_id: 2
}
name: "Fish"
}
Having the pet_id column is irrelevant in that case and I would like to hide it. How?
Use Eloquent API Resources to get an array version of your Models. This is more flexible in the long run than relying on the toArray method of the model which will not be configurable.
If you still want to use toArray, you can simply add the attributes that should not be included to a protected member variable called $hidden in each corresponding model (See documentation about serialization of Eloquent models).
class Pet extends Eloquent
{
public function pet()
{
return hasOne(Man::class)->select('nationality');
}
}
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.
What i know:
$this->$parent->childs(); //we get childs data
what i want to know how:
$this->child->find($id)->parent(); //how to get childs parent without including model in controller | by just using eloquent
heres my sample code of employee and employeeDependent model:
trait EmployeeRelationships{
public function dependents(){
return $this->hasMany(\App\DB\EmployeeDependent\EmployeeDependent::class);
}
}
trait EmployeeDependentRelationships{
/**
* #return mixed
*/
public function employee(){
return $this->belongsTo(\App\DB\Employee\Employee::class, 'employee_id');
}
}
If you want to get the reverse of a BelongsTo relationship you need to specify the inverse of the relationship on the corresponding model. For example:
Employee Class
class Employee extends Model
{
public dependents()
{
return $this->hasMany(Dependant::class);
}
}
Dependent Class
class Dependent extends Model
{
public employee()
{
return $this->belongsTo(Employee::class, 'employee_id');
}
}
With these relationships defined you can then access the relevant models by calling the appropriate methods like so:
$dependents = Employee::first()->dependents; // Returns an eloquent collection
$employee = Dependent::first()->employee; // Returns a model of type Employee
Note that in this example using the first() method to grab a model, you can can do this with any object of the correct type.
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