Many To Many Polymorphic Relations Laravel 5.4 - php

I'd like to establish a many to many polymorphic relation in Laravel. (I'm new to it)
A user can have many profile types
Profile types are like Admin, Webmaster, ProjectManager.
I created a polymorphic relation and a pivot table for the profiles.
class User {
public function profiles(){
return Profile::where('user_id', $this->id);
}
}
class Webmaster { // and class Admin, Projectmanager
public function profiled(){
return $this->morphToMany(Profile::class, 'profileable');
}
public function saveToUser($user)
{
$profile = new Profile;
$profile->user_id = $user->id;
return $this->profiled()->save($profile);
}
}
Now I can save the models to the corresponding User.
$projectManager->saveToUser($user);
$webmaster->saveToUser($user);
It gets all saved to the pivot table as expected and the relations are valid.
profiles table looks like this:
id
user_id
profilable_id
profilable_type
Now the problem is retrieving a model collection of my profiles. I get the Profile types, but I dont get the Webmaster and ProjectManager.
So the question is: how do I get this model collection in this example?

Your model structure is going to be like:
class Webmaster extends Model
{
public function users()
{
return $this->morphToMany('App\Profile', 'userable');
}
}
class Admin extends Model
{
public function users()
{
return $this->morphToMany('App\Profile', 'userable');
}
}
// and ProjectManager, ....
User Model:
class User extends Model
{
public function webmasters()
{
return $this->morphedByMany('App\Webmaster', 'userable');
}
public function admins()
{
return $this->morphedByMany('App\Admin', 'userable');
}
}
Database schema:
webmasters
id - integer
...
admins
id - integer
...
users
id - integer
...
userables
user_id - integer
userable_id - integer
userable_type - string
Now, you can retrieve the relations:
$webmaster = App\Webmaster::find(1);
// retrieve users of a profile
foreach ($webmaster->users as $user) {
//
}
$user = App\User::find(1);
// retrieve webmaster profiles of a user
foreach ($user->webmasters as $webmasters) {
//
}
Actually, your profiles (webmaster, admin, projectmanager) are userable.

Related

Laravel Eloquent Relationship Chain

I'm building a simple notification system.
I'm able to get the logged in users notifications via Auth::user()->notifications but my end goal is to also grab the users info the notification is from.
I'm hoping for an end result of
foreach( Auth::user()->notifications AS $n)
{
echo $n->from->username;
}
currently this throws a "Trying to get property of non-object" error.
Notification table;
id
user_id - notification for this user
from_user_id - notification from this user
User.php;
public function notifications()
{
return $this->hasMany('App\Notification', 'user_id', 'id')->orderBy('notifications.id','desc');
}
public function notificationsUnread()
{
return $this->hasMany('App\Notification', 'user_id', 'id')->where('notifications.seen',null)->orderBy('notifications.id','desc');
}
Notification.php;
public function to()
{
return $this->belongsTo('App\User', 'user_id');
}
public function from()
{
return $this->belongsTo('App\User', 'from_user_id');
}
First you need to have a foreign key set in the table notifications; Then a user can have a notif. and many at the same time. A notif. belongs to a user and many notif. can belong to a user. So on the Notification model you set up the relationship belongsTo like so;
Foreign key:
$table->foreign('from')->refrences('id')->on('users')->onDelete('cascade');
then the relationship:
public function users()
{
return $this->belongsTo('App\User');
}
Then from the controller you can get users info like so;
$userName= Notification::users()->name;
In your case, you're pointing it wrong inreturn you will get only the relationship type instead of data object, since you are calling from like a non method. You should do something like this:
foreach( Auth::user()->notifications AS $n)
{
echo $n->from()->username;
}

laravel - 3 steps relation by many to many

I have 3 tabels: users, teachers And posts.
users:
id - integer
name - string
teachers:
id - integer
teacher_id - integer
user_id - integer
name - string
posts:
id - integer
user_id - integer
title - string
User Model:
class User extends Model
{
public function teachers()
{
return $this->hasMany('App\Teacher');
}
}
Teacher Model:
class Teacher extends Model
{
public function posts()
{
return $this->hasMany('App\Post', 'user_id','teacher_id');
}
}
? Question is How can I use sth like this:
$user = User::find(1);
$teacher_posts = $user->teachers()->posts
I'm sort of new to laravel but here is my take.
What I have realized is that typically your many to many relationships will require a pivot table.
users:(id, name)
teachers:(id, teacher_id, name)
teacher_users:(id, user_id, teacher_id)
posts:(id, user_id, title)
And your Eloquent models will look like this.
class User extends Model
{
public function teachers()
{
return $this->belongsToMany('App\Teacher');
}
public function posts()
{
return $this->hasMany('App\Post');
}
}
class Teacher extends Model
{
public function users()
{
return $this->belongsToMany('App\User');
}
}
$user = User::find(1);
$user_posts = $user->posts();
Check out the documentation here for more details

Laravel ManyToMany Multiple

I have 3 models: User, Role, Tool where each user could have many roles, and each role could have many tools.
The many to many relationships work well in each case. I can access:
User::find(1)->roles
Tool::find(1)->roles
Role::find(1)->tools
Role::find(1)->users
My tables are:
users
id
name
roles
id
name
tools
is
name
role_user
id
role_id
user_id
role_tool
id
role_id
tool_id
In each model:
//In User Model
public function roles()
{
return $this->belongsToMany('Rol');
}
//In Role Model
public function users()
{
return $this->belongsToMany('User');
}
public function tools()
{
return $this->belongsToMany('Tool');
}
//In Tool Model
public function roles()
{
return $this->belongsToMany('Rol');
}
I need to get all the tools of a single user like: User::find(1)->roles()->tools. How can I do that?
Get all the roles of the user, then in a loop you get all tools of the role and merge them to an array where you store all tools.
$tools = array();
foreach(User::find(1)->roles as $role)
$tools = array_merge($tools, $role->tools->toArray());
This runs a query for every iteration, so for better performance you should use eager loading.
$tools = array();
foreach (User::find(1)->load('roles.tools')->roles as $role) {
$tools = array_merge($tools, $role->tools->toArray());
}
Now you can place this to a function called tools() in your User model.
public function tools()
{
$tools = array();
foreach ($this->load('roles.tools')->roles as $role) {
$tools = array_merge($tools, $role->tools->toArray());
}
return $tools;
}
You can call it like this: User::find(1)->tools().
I don't think that the framework has a better solution. One other method is to use the Fluent Query Builder and create your own query but I don't see how that would be better.
Define a hasManyThrough relationship in User::find(1)->roles()->tools
class User extends Eloquent {
public function tools()
{
return $this->hasManyThrough('Tool', 'Role');
}
}
Then you can access straight forward:
$user->tools

Laravel 4 many to many get all data from both tables

I have tables: users, resources and pivot table user_resources.
users
id
username
etc.
resources
id
resource_name
etc.
user_resources
id
user_id
resource_id
User model:
class Resources extends Eloquent {
public function users() {
return $this->belongsToMany('User', 'user_resources');
}
}
and resource model:
class User extends Eloquent {
public function resources() {
return $this->belongsToMany('Resource', 'user_resources');
}
}
How can I get all of the users and all of the resources that belongs to the users.
Probably you just have to:
$everything = User::with('resources')->get();

Laravel Pivot Table and indirect relationship

I'm writing a survey with Laravel 4 and need the ability for users to be able to take the same survey multiple times (and have their answers saved as different instances.)
I currently have a pivot table called survey_user that links a user to an invited survey. A potentially positive side effect of the pivot table is that its primary key could be used to have unique survey instances.
My problem is figuring out how to get answers, specifically through the user model. Answers table would contain a foreign key to the primary of the pivot table.
My User model:
class User extends Eloquent {
public function surveys() {
return $this->belongsToMany('Survey', 'survey_user')
->withPivot('id', 'completed_at');
}
public function answers() {
// This should return all of the user's answers, irrespective of
// survey id's.
}
}
Tables:
surveys: id
users: id
survey_user: id, survey_id, user_id, completed_at
answers: survey_user_id, answer_text, ...
How might I accomplish this psuedo-relationship or perhaps a better way to structure?
Use relationships! Here's how I would do it:
class User extends Eloquent {
public function surveys() {
return $this->belongsToMany('Survey');
}
public function answers() {
return $this->hasMany('Answer');
}
}
class Survey extends Eloquent {
public function surveys() {
return $this->belongsToMany('User');
}
public function answers() {
return $this->hasMany('Answer');
}
}
class Answer extends Eloquent {
public function survey() {
return $this->belongsTo('Survey');
}
public function user() {
return $this->belongsTo('User');
}
}

Categories