Getting property from a hasOne relationship of a collection Laravel 5.3 - php

I have 3 models : Group, User, and Profile
Group relates to User with many to many relationship,
User relates to Profile with one to one relationship,
and User also has many to many relationship with Role model
the question is how to get the faculty property of profiles from user in a group whose role are "mentee" ?
i tried this, but it doesn't worked:
$faculties = collect($this->mentee()->profile->faculty;
this is the Group.php and the mentee() method
class Group extends Model
{
public function users()
{
return $this->belongsToMany(User::class);
}
public function mentee()
{
return $this->users()->whereHas(
'roles', function($q){
$q->where('name', 'mentee');
})
->get();
}
here's the User.php
class User extends Authenticatable
{
protected $fillable = [
'username', 'email', 'password',
];
public function profile()
{
return $this->hasOne(Profile::class);
}
public function owns($related)
{
return $this->id == $related->user_id;
}
public function groups()
{
return $this->belongsToMany(Group::class);
}
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function hasRole($role)
{
if (is_string($role)) {
return $this->roles->contains('name', $role);
}
return !! $this->intersect($this->roles)->count();
}
}
lastly, here's the Profile.php
class Profile extends Model
{
protected $fillable = [
'user_id', 'name', 'nim', 'faculty', 'major', 'batch','religion', 'gender', 'phone', 'line_id',
];
public function user()
{
return $this->belongsTo(User::class);
}
}
please let me know if i should give more details

Related

how can i join multiple tables in eloquent using relationships?

How should i join these 4 tables users, pages, category, products using relationships intead in controller.I also prefer calling these functions from corresponding models using respective function names but not database column names in view.
These are my models:
User model:
class User extends Authenticatable{
use HasFactory, Notifiable;
protected $fillable = ['id','name' ];
protected $hidden = [ 'password', 'remember_token', ];
protected $casts = ['email_verified_at' => 'datetime', ];
public function getuserName(){
if($this->name){ return "$this->name"; }
return null;
}
public function page(){
return $this->hasMany('App\Models\Pages', 'user_id');
}
public function product(){
return $this->hasMany('App\Models\Products', 'user_id');
}
}
Products model:
class products extends Model {
use HasFactory;
protected $table = 'products';
protected $fillable = [ 'id', 'user_id', 'parent_page_id', 'pcategory_id', 'prodname', ];
/**get id(PK)****/
public function fetchid(){
if($this->id){ return $this->id; }
return null;
}
/**get pageid (FK)****/
public function fetchpageid(){
if($this->parent_page_id){ return $this->parent_page_id; }
return null;
}
/**get categoryid (FK)****/
public function fetchcategoryid(){
if($this->pcategory_id){ return $this->pcategory_id; }
return null;
}
/**get product owner****/
public function fetchuser_id(){
if($this->user_id){ return $this->user_id; }
return null;
}
/**get product name****/
public function fetchprodname(){
if($this->prodname){ return $this->prodname; }
return null;
}
/**pick session userid from User model****/
public function user(){
return $this->belongsTo('App\Models\User', 'user_id');
}
}
Post model:
class pages extends Model {
use HasFactory;
protected $table = 'pages';
protected $fillable = [ 'page_id', 'user_id', 'pagename', ];
/**get page id(PK)****/
public function fetchpage_id(){
if($this->page_id){ return $this->page_id; }
return null;
}
/**get page owner****/
public function fetchuser_id(){
if($this->user_id){ return $this->user_id; }
return null;
}
/**get page name****/
public function fetchpagename(){
if($this->pagename){ return $this->pagename; }
return null;
}
/**pick session userid from User model****/
public function user(){
return $this->belongsTo('App\Models\User', 'user_id');
}
}
Category model:
class category extends Model {
use HasFactory;
protected $table = 'category';
protected $fillable = [ 'category_id', 'name', ];
/**get category id(PK)****/
public function fetchcategory_id(){
if($this->category_id){ return $this->category_id; }
return null;
}
/**get category name****/
public function fetchcname(){
if($this->name){ return $this->name; }
return null;
}
}
How should i join these 4 tables users, pages, category, products using relationships intead
$carousel = Products::where(function($querycarousel ) {
return $querycarousel
->leftJoin('users', 'products.user_id', 'users.id')
->leftJoin('pages', 'products.parent_page_id', 'pages.page_id')
->leftJoin('category', 'products.pcategory_id', 'category.category_id')
->where('products.verification_status', 'Verified')
->where('category.name', 'New');
})->inRandomOrder()
->limit(50)
->get();
return view('pages.home')->with('carousel ', $carousel );
View
I also prefer calling these functions from corresponding models using respective function names but not database column names
#foreach ($carousel->chunk(5) as $key => $batchresults)
#foreach ($batchresults as $key => $feed)
<div>
<p>{{ $feed->fetchprodname() }}</p>
<p>{{ $feed->fetchcname() }}</p>
<p>{{ $feed->fetchpagename() }}</p>
<p>{{ $feed->getuserName() }}</p>
</div>
#endforeach
#endforeach

Laravel Eloquent get all Posts stored in categories with Roles

I have four tables in a database named: Category, User, Role and then Post. In the Category table I have a column category_id which by this column i can have multiple child in category.
Every user belongsToMany roles and categories and each category belongsToMany posts, i must get all posts by role which logged into our application
As you can see in below screen shot manager 1 and manager 2 belongsToMany programings, dart, flutter and php.
you can suppose manager 1 user id is 1 and manager 2 is 2 and both of them are manager role
my question is how can i get all posts which logged user belongsToMany categories by role
logged user is manager 1 and i want to get all posts which saved into categories from parent which that's PROGRAMINGS
for example:
$categories = Category::whereNull('category_id')->whereHas('users.roles', function($q){
return $q->whereLabel('is-manager');
})->with(['posts' => function ($query) {
$query->with('language');
}])->get();
dd($categories->pluck('posts'));
NOTE:
with #Med.ZAIRI answer which posted on this thread every user in MANAGER 2 which is't synced into MANAGER 1, can see all of MANAGER 1 posts
In the Model Category add a relationship, like:
/**
* this will get the parent category
*/
public function parentCategory()
{
return $this->belongsTo( Category::class, 'category_id', 'id' );
}
Then, try to get Posts with their categories and their parent
Categories, and the users with their Roles, like:
$posts = Post::with( ['category.parentCategory', 'user.roles'])->get()
my used models in this senario:
class Category extends Model
{
use SoftDeletes;
protected $guarded = ['id'];
protected $hidden = ['id', 'category_id'];
public function parentCategory()
{
return $this->belongsTo( Category::class, 'category_id', 'id' );
}
public function categories()
{
return $this->hasMany(Category::class);
}
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function posts()
{
return $this->belongsToMany(Post::class);
}
public function users()
{
return $this->belongsToMany(User::class);
}
public function childrenCategories()
{
return $this->hasMany(Category::class)->with('categories');
}
}
class Role extends Model
{
protected $guarded = ['id'];
public function users()
{
return $this->belongsToMany(User::class);
}
public function permission()
{
return $this->belongsToMany(Permission::class);
}
public function hasPermission($permission)
{
return !!$permission->intersect($this->roles->permission)->count();
}
}
class User extends Authenticatable
{
use Notifiable, SoftDeletes, UsersOnlineTrait;
protected $guarded = [
'id',
];
protected $hidden = [
'password', 'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
'avatar_path' => 'array',
'experiences' => 'array',
];
public function group()
{
return $this->belongsToMany(UserGroup::class, 'user_user_group');
}
public function child()
{
return $this->hasMany(User::class)->with('child');
}
public function parent()
{
return $this->belongsTo(User::class, 'user_id');
}
public function properties()
{
return $this->hasOne(UsersProperty::class);
}
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function hasRole($role)
{
return $this->roles->contains('id', $role);
/*if (is_string($role)) {
} else {
return !!$role->intersect($this->roles)->count();
}*/
}
public function hasRoleByName($role)
{
if ($role == null) return false;
if (is_string($role)) {
return $this->roles->contains('name', $role) || $this->roles->contains('label', $role);
} else {
return !!$role->intersect($this->roles)->count();
}
}
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
In the Model Category add a relationship, like:
/**
* this will get the parent category
*/
public function parentCategory()
{
return $this->belongsTo( Category::class, 'category_id', 'id' );
}
Then, try to get Posts with their categories and their parent Categories, and the users with their Roles, like:
$posts = Post::with( ['category.parentCategory', 'user.roles'])->get()
Trait with methods to get all available posts for the logged in user
based on the role
class User extends Model
{
use HasFactory, Notifiable, HasPosts;
}
<?php
namespace App\Concerns;
use App\Models\Category;
use Illuminate\Support\Str;
use Illuminate\Support\Collection;
trait HasPosts
{
/**
* Get all available posts for the currently logged in user
*
* #return void
*/
public function posts()
{
$method = 'postsFor' . Str::studly(str_replace('is-', '', $this->roles->first()->label));
return $this->{$method}()->collapse();
}
/**
* Get all posts associated with all categories including
* their subcategories for the logged in Portal Manager
*/
public function postsForPortalManager(): Collection
{
return Category::with([
'subcategories.posts.language',
'posts.language'
])
->get()
->pluck('posts');
}
/**
* Get all posts for the logged in Manager which belong to
* one of the categories associated with the Manager
*/
public function postsForManager(): Collection
{
return $this->categories()
->with('posts.language')
->get()
->pluck('posts')
->filter(function ($collection) {
return !!$collection->count();
});
}
/**
* Get only the posts which belong to the categories for the Editor
* and which are authored by the logged in Editor
*/
public function postsForEditor(): Collection
{
return $this->categories()
->with([
'posts' => function ($query) {
$query->where('user_id', $this->id)->with('language');
},
'posts.language'
])
->get()
->pluck('posts')
->filter(function ($collection) {
return !!$collection->count();
});
}
/**
* Get only the posts which belong to the categories for the Writer
* and which are authored by the logged in Writer
*/
public function postsForWriter(): Collection
{
return $this->categories()
->with([
'posts' => function ($query) {
$query->where('user_id', $this->id)->with('language');
},
'posts.language'
])
->get()
->pluck('posts')
->filter(function ($collection) {
return !!$collection->count();
});
}
}
Then for any authenticated user we can fetch available posts with
$user->posts()
It works with the seed data you have provided.
ella is not able to see the post on Flutter and scarlett is not able to see the post on laravel
Only assumption here is that have taken the first role of the authenticated user to lookup the method used.
Add this to your roles model:
public function categories()
{
return $this->hasMany(Category::class);
}
After that you can reach posts from the user, like:
$authorizedUser->roles()->with('categories.posts')->get();
You can flatten the result to access posts directly as well
If your relationships are all many-to-many as below:
roles >-< users >-< categories >-< posts
and are all defined properly in the models, e.g.
// Role.php
public function users()
{
return $this->belongsToMany(User::class);
}
// User.php
public function categories()
{
return $this->belongsToMany(Category::class);
}
// Category.php
public function posts()
{
return $this->belongsToMany(Post::class);
}
then I'm pretty sure you should be able to do
$role = Role::find(1);
// get all posts from all categories from all users with $role
$posts = $role->users()->categories()->posts;

How to query through nested Laravel relationships the eloquent ORM way

I have a relationship that is almost 5 levels deep.
In my blades I use this all time without a problem. For example:
{{ $user->team->department->region->company->name ?? ''}}
How would I go about querying all users that belong to a company?
$users = User::where($user->team->department->region->company->id, '=', 1)->get(); ?????
Company Relationships:
class Company extends Model
{
public function region() {
return $this->hasMany('App\Region', 'company_id', 'id');
}
}
Region Relationships:
class Region extends Model
{
public function company() {
return $this->hasOne('App\Company', 'id', 'company_id');
}
public function department() {
return $this->hasMany('App\Department', 'region_id', 'id');
}
}
Department Relationships:
class Department extends Model
{
public function region() {
return $this->hasOne('App\Region', 'id', 'region_id');
}
public function team() {
return $this->hasMany('App\Team', 'department_id', 'id');
}
}
Team Relationships:
class Team extends Model
{
public function department() {
return $this->hasOne('App\Department', 'id', 'department_id');
}
public function user() {
return $this->hasMany('App\User', 'team_id', 'id');
}
}
User Relationships:
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function team() {
return $this->hasOne('App\Team', 'id', 'team_id');
}
}
I know there must be some easy way to query through nested relationships that Laravel provides a way for or a some facility for, but I have yet to find any decent examples from Googling around.
You can use this package for your need.
https://github.com/staudenmeir/eloquent-has-many-deep
read the instructions, depth of the relationship is not limited.

Problems calling relationships in Laravel

I'm getting problems calling relationships in laravel, I have 4 tables: users, tickets, stores, statuses. and I have a #OneToMany relationship in Users to Tickets (1 user have many tickets). the other relationships are #OneToOne (1 ticket have 1 store and status).
Now, I have 6 tickets in my table and 4 users, I can print the relationship to the 4 first tickets, but when I want to call the ticket 5 or 6, the relationship dissapears.
The same thing with store and status, I can print the relationship while the id of the ticket is not greater than the number of items I have in my table.
these are my models:
User Model:
class User extends Authenticatable
{
use Notifiable, HasRoles;
protected $fillable = [
'id','name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function tickets()
{
return $this->hasMany(Ticket::class, 'usuario_id');
}
}
Ticket Model:
class Ticket extends Model
{
protected $fillable = [
'comentarios', 'falla', 'modelo', 'no_serie', 'monto',
'usuario_id', 'status_id', 'store_id'
];
public function user()
{
return $this->belongsTo(User::class, 'id');
}
public function store()
{
return $this->hasOne(Store::class, 'id');
}
public function status()
{
return $this->hasOne(Status::class, 'id');
}
}
Store Model:
class Store extends Model
{
protected $table = "stores";
protected $primaryKey = 'id';
public $timestamps = false;
protected $fillable = [
'sucursal', 'dirección'
];
public function ticket()
{
return $this->belongsTo(Ticket::class, 'store_id');
}
}
Status Model:
class Status extends Model
{
public $timestamps = false;
protected $fillable = [
'status'
];
public function ticket()
{
return $this->belongsTo(Ticket::class, 'status_id');
}
}
Controller:
$tickets = Ticket::all();
return view('Admin.index', compact('tickets'));
View
#foreach($tickets as $ticket)
<li>{{ $ticket->user }}</li>
#endforeach
result:
Result of the foreach
In the view, I'm calling all the tickets ($tickets), and for each ticket, I print the relationship (user function). But in the result, you can see that just print first 4 relationships, (the number of my users), if I add 1 user, the relationship in the 5th ticket appears.
The Same problem with the other tables (store and status).
Replace user() relationship in Ticket moedel to:
public function user()
{
return $this->belongsTo(User::class, 'usuario_id', 'id');
}
in Ticket model you must change function to
public function user()
{
return $this->belongsTo(User::class, 'usuario_id', 'id');
}
or just public function user()
{
return $this->belongsTo(User::class);
}

Laravel ORM relationship method 'BelongsToMany' throwing error

Summary
I am receiving the following error when trying to call the relationship:
Object of class Illuminate\Database\Eloquent\Relations\BelongsToMany
could not be converted to string
My setup is very basic, and consists of two models, User and Role.
User Model [User.php]
<?php
use Illuminate\Auth\UserInterface;
class User extends Eloquent implements UserInterface {
protected $table = 'users';
protected $hidden = array('password');
protected $fillable = array('id', 'username', 'password');
public function getAuthIdentifier() {
return $this->getKey();
}
public function getAuthPassword() {
return $this->password;
}
}
Role Model [Role.php]
<?php
class Role extends Eloquent {
protected $table = "roles";
protected $fillable = array(
'id',
'code',
'name'
);
public function foo() {
return $this->belongsToMany('User', 'map_role_user', 'role_id', 'user_id');
}
}
And finally I'm calling the method foo in the routes file, example:
Route::get('role', function() {
return Role::find(1)->foo();
});
From
https://laravel.com/docs/5.3/eloquent-relationships or https://laravel.com/docs/4.2/eloquent#relationships
If a collection is cast to a string, it will be returned as JSON:
<?php
$roles = (string) User::find(1)->roles;
If you dont want to add further constraints to the query then you have to use dynamic properties concept. So,
$user = App\User::find(1);
foreach ($user->posts as $post) {
//
}
If you want to add more constraints then do this
App\User::find(1)->posts()->where('title', 'LIKE', '%Best%')->get()

Categories