Laravel variable model polymorphic - php

I have a table as follows in my database:
table area_blocks;
id
owner_type
owner_id
created_at
updated_at
in the owner_type field it has the Eloquent Model name and the owner_id is the id of that model in the database. Example:
db: area_blocks
id | owner_type | owner_id
1 | App\Models\Title | 3
2 | App\Models\Title | 4
3 | App\Models\Textarea | 1
So I'm expecting when I fetch all of these to also eager load the relevant field from the eloquent model stored in owner_type.
Is there an eloquent relationship that can bring back that record from the owner_type field using eager loading? I've tried $this->morphTo(), e.g.
public function block()
{
return $this->morphTo();
}
but that is returned as null. Any ideas how this can be done?
Example code;
<?php
namespace App\Models;
use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Database\Eloquent\Model;
class AreaBlocks extends Model
{
protected $with = ['block'];
public function block()
{
return $this->morphTo();
}
}
Route::get('/', function(){
return App\Models\AreaBlocks::all();
});

You have to specify the column name/prefix:
public function block()
{
return $this->morphTo('owner');
}
Or rename the relationship:
public function owner()
{
return $this->morphTo();
}

Related

Laravel Eloquent for pivot table with 2 foreign keys to a table and 1 foreign key to another table

I have tables as follows where role_id is the foreign key of the roles table and user_id and setter_id are the foreign key of the users table.
table 1:
+---------------------+
| users |
+---------------------+
| id |
| name |
| email |
| password |
+---------------------+
table 2:
+---------------------+
| roles |
+---------------------+
| id |
| name |
+---------------------+
pivot table:
+---------------------+
| role_user |
+---------------------+
| role_id |
| user_id |
| setter_id |
+---------------------+
The models I have defined:
User Model:
class User extends Model
{
public $timestamps = false;
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
Role Model:
class Role extends Model
{
public $timestamps = false;
public function users()
{
return $this->belongsToMany(User::class);
}
}
How do I change my models so that I can get the data as shown below?
user -> roles -> setter : The user and its roles and the setter of each role for user
Thank you...
You will never be able to access the setter by calling it in the roles collection.
This is wrong:
$user->roles->setter
Let's see an example that will work:
foreach($user->roles as $role)
{
dd($role->pivot->setter)
}
To be able to do that, you need to change your models to reflect something like this:
User
class User extends Model
{
public $timestamps = false;
public function roles()
{
return $this->belongsToMany(Role::class)
->using(UserRolePivot::class)
->withPivot([
'role_id',
'user_id',
'setter_id',
]);
}
}
Role
class Role extends Model
{
public $timestamps = false;
public function users()
{
return $this->belongsToMany(User::class)
->using(UserRolePivot::class)
->withPivot([
'role_id',
'user_id',
'setter_id',
]);
}
}
Pivot
use Illuminate\Database\Eloquent\Relations\Pivot;
class UserRolePivot extends Pivot
{
protected $fillable = [
'role_id',
'user_id',
'setter_id',
];
public function role()
{
return $this->belongsTo(Role::class , 'role_id');
}
public function user()
{
return $this->belongsTo(User::class , 'user_id');
}
public function setter()
{
return $this->belongsTo(User::class , 'setter_id);
}
}
You can either update the belongsToMany calls to include the setter_id on the pivot aswell, and then access it via ->pivot->setter_id and retrieve a model using that id.
return $this->belongsToMany(Role::class)->withPivot('setter_id');
Or (and what I would personally go for) you could define a custom pivot model, and create a setter() relationship there, so you could retrieve the model directly from the pivot.

Make conditional Eloquent relationship in Laravel

Laravel 5.7. I have an Eloquent model Theme, with two fields, id and name.
Another model, Filter, has three fields: id, name, theme_id.
Filter:
class Filter extends Model
{
public function theme()
{
return $this->belongsTo('App\Theme');
}
}
I can attach these filters to an arbitrary number of other models, e.g. the model Foo has two fields, id and name. I attach the filter to it using a Filterables table:
Filterables:
id | filter_id | filterable_id | filterable_type
------------------------------------------------
1 | 1 | 3 | App\Foo
The above example shows that the Filter of id 1 is attached to the Foo of id 3.
Now to get all the filters of Foo, I have this relationship in my Foo model:
Foo:
class Foo extends Model
{
public function filters()
{
return $this->morphToMany('App\Filter', 'filterable');
}
}
This all works fine. But now I want to get the Foo model, and only the filters where the filter's theme_id is (for example) 1.
How can I add this condition to the filters relationship?
Just add a where clause directly to your relationship
class Foo extends Model
{
public function filters()
{
return $this->morphToMany('App\Filter', 'filterable')->where('theme_id', 1);
}
}

Laravel eloquent has hasmany of hasmany

How to show all company who has photo attachment?
company:
id | name
user:
id | name | company_id
post:
id | user_id | text
post_attachment:
id | post_id | path | type
company model:
public function users() {
return $this->hasMany('App\User')->orderBy('id', 'ASC');
}
user model:
public function posts() {
return $this->hasMany('App\Post');
}
posts model:
public function images(){
return $this->hasMany('App\PostsAttachment')->where("type", "image");
}
I want to get all company who have user(s) that have post(s) with minimal 2 images attachment. Anyone can help me?
I tried Company::has('users.posts.images', '<', 2)->get(); but it also give companies who has user image below 2.
Using eloquent you could write your logic as
$companies = Company::has('users.posts.images')->get();
See Querying Relationship Existence

Laravel 5.4 | Fetching data from Pivot Table

I have 4 tables in my database:
Table 1: Category
---|------
id | name
---|------
1 | Cars
In 'Category' model class I have defined the following relationship:
class Category {
public function fields() {
return $this->belongsToMany('App\Field');
}
}
Table 2: Field
id | name
---|-------
1 | Make
In 'Field' model class I have defined the following relationship:
class Field {
public function categories() {
return $this->belongsToMany('App\Category');
}
}
Table 3: Field_Options
field_id | value
---------|-------
1 | Audi
1 | BMW
In 'FieldOption' model class I have defined the following relationship:
class FieldOption extends Model
{
public function field() {
return $this->belongsTo('App\Field');
}
}
Table 4: Category_Field
category_id | field_id
------------|-------
1 | 1
Now I need to fetch all the fields and field_options for category_id=1. How can I achieve this using Laravel?
Thanks!
First define relationship between Field and FieldOptions
public function options() {
return $this->hasMany('App\FieldOption');
}
Then you can eager load all relationships like this
$category = Category::with('fields.options')->find(1);
//Get category 1, with all fields and their respectif fieldOptions

laravel how to get all the users i talked to

i am now working on a messaging system with laravel. Now i want to have a list of users the current user send message to / receive from. suppose i have a message table like
id | sender_id | receiver_id | msg
1 | 1 | 2 | smadksamdksa
2 | 3 | 4 | hi
3 | 1 | 2 | www
4 | 2 | 1 | ssse
5 | 3 | 1 | hi
i find get a list of id of user i talked to, the result for the user 1 will be
id
2
3
model of message
namespace App;
use Illuminate\Database\Eloquent\Model;
class msg extends Model
{
protected $table = 'msgs';
public function user()
{
return $this->belongsTo('App\user');
}
}
the query i made
$senders = msg::select('sender_id')->where('receiver_id', '=', Auth::id())->distinct()->get();
$peopleUserTalkedTo = msg::select('receiver_id')->where('sender_id', '=', Auth::id())->distinct()->union($senders)->get();
but it doesn't work with an error
Undefined property: Illuminate\Database\Eloquent\Collection::$bindings
what's wrong with it, and can i SELECT sender id and receiver AS id, can i get the user id from it later on?
I think the problem is about the union method.
You should define your models like this:
namespace App;
use Illuminate\Database\Eloquent\Model;
class msg extends Model
{
protected $table = 'msgs';
public function sender()
{
return $this->belongsTo('App\user','sender_id');
}
public function receiver()
{
return $this->belongsTo('App\user','receiver_id');
}
}
namespace App;
use Illuminate\Database\Eloquent\Model;
class user extends Model
{
public function talkedTo()
{
return $this->hasMany('App\msg','sender_id');
}
public function relatedTo()
{
return $this->hasMany('App\msg','receiver_id');
}
}
Now try to fetch people you talked to like this:
Auth::user()->talkedTo()->get();
Auth::user()->relatedTo()->get();
Updated
For getting only ids of the people you talked to or related to follow the code:
Auth::user()->talkedTo->pluck('id');
Auth::user()->relatedTo->pluck('id');
didnt realy get what u want but Try this after being sure to add this to ur user model
class user extends Model
{
public function msgs()
{
return $this->hasMany('App\msg');
}
}
then
$mymsgs = Auth::user()->msgs->get(); //collection of all msgs
and then you can use a foreach loop

Categories