How to Create Relation in Eloquent Relationships Laravel - php

I have Two Table
1- projects
User with id 5 has created 3 project - which means he will have 3 unique conversation with our different agent
----------------------------------------
|id | user_id | title | time |
|1 | 5 | Example | 2018-06-30 |
|2 | 5 | Example | 2018-06-30 |
|3 | 5 | Example | 2018-06-30 |
----------------------------------------
2- conversation
-------------------------------------------
|id | project_id | user_one | user_two |
|1 | 1 | 5 | 3 |
|2 | 2 | 5 | 7 |
|3 | 3 | 5 | 10 |
-------------------------------------------
Whenever a project is created, a conversation is created with that project id, Now in Laravel i want to get that project detail using Eloquent Relationships.
User_one is the project creator and user_two is our agent assigned to that product.
This is What I've tried
class Chat extends Model {
public function project()
{
return $this->belongsTo('App\ProjectModel');
}
}
class ProjectModel extends Model
{
public $table = 'projects';
}
Here is the controller function
public function Progress($id){ // Id passed here is 2, so it should show detail of project number 2
return \App\Chat::find($id)->project()->get();
}
After all this I'm getting an error - Call to a member function project() on null

You can try like this with creating 2 Models Project and Conversation
table
conversations(id, project_id, creator, agent)
Project Model
public function conversations(){
return $this->hasMany('App\Conversation');
}
Conversation Model
public function project(){
return $this->belongsTo('App\Project', 'project_id');
}
public function creatorUser(){
return $this->belongsTo('App\User', 'creator');
}
public function agentUser(){
return $this->belongsTo('App\User', 'agent');
}
Fetch Data
public function Progress($id){ // Id passed here is 2, so it should show detail of project number 2
$chats = Conversation::with('project', 'creatorUser', 'agentUser')->where('project_id', 2)->get();
foreach($chats as $chat){
dd($chat->project); //it will always print same project because we have filter the conversation by project_id
dd($chat->creatorUser);
dd($chat->agentUser);
}
}

you can create a relation Along with specifying foreign Key and owner key like:
class Chat extends Model {
public function project()
{
return $this->belongsTo(App\ProjectModel::class, 'project_id', 'id');
}
}
and then you will be able to get:
\App\Chat::where('id', $id)->first()->project;

Related

Three-way pivot Table Laravel

I'm struggling to connect three models in my Laravel app. The models are Bottle, Label and Spirit. I want to get all the labels based on bottle_id and spirit_id so I created a pivot table to store the relationships between Bottle-Label-Spirit. Please see below my current setup.
DB
+---------+--------+---------+-------------------------+
| bottles | labels | spirits | bottle_label_spirit |
+---------+--------+---------+-------------------------+
| id | id | id | id |
| name | name | name | bottle_id |
| | | | label_id |
| | | | spirit_id |
| | | | created_at |
| | | | updated_at |
+---------+--------+---------+-------------------------+
Where bottle_label_spirit is my pivot table
BOTTLE CLASS
class Bottle extends Model
{
public function labels() {
return $this->belongsToMany(Label::class)->withTimestamps();
}
public function spirits() {
return $this->belongsToMany(Spirit::class)->withTimestamps();
}
}
LABEL CLASS
class Label extends Model
{
public function bottles() {
return $this->belongsToMany(Bottle::class)->withTimestamps();
}
public function spirits() {
return $this->belongsToMany(Spirit::class)->withTimestamps();
}
}
SPIRIT CLASS
class Spirit extends Model
{
public function labels() {
return $this->belongsToMany(Label::class)->withTimestamps();
}
public function bottles() {
return $this->belongsToMany(Bottle::class)->withTimestamps();
}
}
QUESTIONS
So my questions are:
Is this the right approach to handle this manyToMany relationships?
If yes, how do i get all the labels where bottle_id = 1 and spirit_id = 1
You do not need a 4th table for this, you can accomplish all of this using hasManyThrough. This will allow you to query distant relationships.

Laravel 5.5 User model and friends relationship (belongsToMany) by multiple columns

Problem
I created a simple friendship relationship for my Laravel app which all worked ok until I noticed that when I queried the friendship of a user it would only search the current user on the UID1 field.
Since friendships are in essence a two-way relationship, Im trying to find a way in a laravel Model to retrieve ALL friendships relations by multiple columns.
Current Implementation
public function friends()
{
return $this->belongsToMany( App\Modules\Users\Models\User::class ,'friends', 'uid1');
}
Ideal Implementation
public function friends()
{
$a = $this->belongsToMany( App\Modules\Users\Models\User::class ,'users_friends', 'uid1');
$b = $this->belongsToMany( App\Modules\Users\Models\User::class ,'users_friends', 'uid2');
return combine($a,$b);
}
Table Structure
+----------------------+
| users table |
+----------------------+
+----| id: primary UserID |
| | fname: string |
| +----------------------+
|
|
| +----------------------+
| | friends table |
| +----------------------+
| | id: primary iD |
| | |
+----| uid1: user_id |
| | |
+----| uid2: user_id |
+----------------------+
The current implementation will only result in 1 of these records returning if the Current UserID = 1 as per the data in the friends table below.
+-------------------------------+
| friends table (data) |
+--------|---------|------------+
| id | uid1 | uid2 |
+--------|---------|------------+
| 1 | 1 | 7 |
| 2 | 7 | 1 |
| 3 | 9 | 1 |
+-------------------------------+
User Model
<?php
namespace App\Modules\Users\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'users';
protected $fillable = [
'username', 'email', 'password', .... .
];
public function friends()
{
return $this->belongsToMany( App\Modules\Users\Models\User::class ,'users_friends', 'uid1');
}
Environment
Server = Homestead/linux
PHP = 7
MySQL
Update
I have a FriendShip helper class I created which does something similar, however in this function I pass in the UserID explicitly
Friendship::where( [
[ 'uid1' ,'=', $uid],
])->orWhere( [
[ 'uid2', '=', $uid]
])->all();
You can add additional conditions when you're declaring relationship by simply chaining it.
<?php
//...
class User extends Model {
//...
public function friends() {
return $this->hasMany(/*...*/)->orWhere('uid2', $this->id);
}
//...
But keep in mind that eloquent is not grouping the first conditions of relation in parenthesis so you might end with SQL that will not work as expected in some cases (if using or, and should be fine)
For example the above might result in a SQL that looks like this
SELECT * FROM users_friends WHERE uid1 = ? AND uid1 IS NOT NULL OR uid2 = ?
Which is a correct SQL statement but without grouping you will not get the result that you're expecting.
Another way is to use accessor and two separate relationships
<?php
//...
public function friends1() {
return $this->belongsToMany(User::class, 'users_friends', 'uid1');
}
public function friends2() {
return $this->belongsToMany(User::class, 'users_friends', 'uid2');
}
public function getFriendsAttribute() {
return $this->friends1->merge($this->friends2);
}
//...
But this way you get two separate trips to DB.

Laravel: N to N (mysql) relation using Eloquent ORM

I got 4 tables:
// Table countries
+----+------+
| Id | Name |
+----+------+
| 1 | USA |
| 2 | GB |
+----+------+
// Table platforms
+----+---------+
| Id | Name |
+----+---------+
| 1 | Windows |
| 2 | Linux |
+----+---------+
// Table users
+----+-------+------------+-------------+
| Id | Name | country_id | platform_id |
+----+-------+------------+-------------+
| 1 | Admin | 1 | 1 |
| 2 | Test | 2 | 1 |
+----+-------+------------+-------------+
// Table posts
+----+-----------+------------+-------------+---------+
| Id | Title | country_id | platform_id | user_id |
+----+-----------+------------+-------------+---------+
| 1 | TestPost1 | 2 | 1 | 1 |
| 2 | TestPost2 | 2 | 2 | null |
+----+-----------+------------+-------------+---------+
The database should be able to implement the following relations:
User (N) <-> (N) Platform
User (N) <-> (N) Country
User (0..1) <-> (N) Post
Post (N) <-> (N) Country
Post (N) <-> (1) Platform
So now I tried to implement these relations following Laravel Eloquent ORM documentation:
// Country.php
public function posts()
{
return $this->belongsToMany('App\Post');
}
public function users()
{
return $this->belongsToMany('App\User');
}
// Platform.php
public function users()
{
return $this->belongsToMany('App\User');
}
public function posts()
{
return $this->belongsToMany('App\Post');
}
// User.php
public function posts()
{
return $this->hasMany('App\Post');
}
public function countries()
{
return $this->hasMany('App\Country');
}
public function platforms()
{
return $this->hasMany('App\Platform');
}
// Post.php
public function countries()
{
return $this->hasMany('App\Country');
}
public function platforms()
{
return $this->hasMany('App\Comment');
}
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
But now I am confused, as I thought the way to implement N to N relations in mysql is to add a third table to db, for example like that:
// Table CountryUserRelations to implement User (N) <-> (N) Country
+----+------------+---------+
| Id | country_id | user_id |
+----+------------+---------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 1 | 2 |
| 4 | 2 | 2 |
+----+------------+---------+
But how does Eloquent ORM handle the rules inside my model? Will it keep the N to N relations without having to add a relations table? Or am I missing something or misunderstanding the Eloquent ORM Relations concept?
I just joined stackoverflow so I do not have enough credit to comment so I will leave an asnwer here.
First of all please correct your relationship definition.
in User Model:( you have mistake here)
public function countries(){
return $this->belongsToMany(Country::class);
}
and in your Country Model:
public function users(){
return $this->belongsToMany(User::class);
}
second you need to create country_user table using:
php artisan make:migration create_country_user_table
after it you need to complete your table:
Schema::create('country_user', function (Blueprint $table){
$table->increments('id');
$table->unsignedInteger('country_id');
$table->unsignedInteger('user_id');
$table->foreign('country_id')->references('id')->on('countries');
$table->foreign('user_id')->references('id')->on('users');
}

Laravel count Eloquent belongsToMany related model

I'm new to Laravel, and I got stuck with the following issue:
I have a table for the users, and groups, and a table for connecting them. The general task any user can join any group.
----------------------------------------------
| users | groups | user_groups |
|--------------------------------------------|
| id - int pk | id - pk | id - pk |
| name text | name | user_id - fk |
| email | | group_id - fk |
| phone | | any_attr |
----------------------------------------------
I have the following models:
class User
{
...
public function groups()
{
return $this->belongsToMany(Group::class, 'user_groups')->withPivot(['is_notification_requested']);
}
...
}
class Group
{
...
public function users()
{
return $this->belongsToMany(User::class, 'user_groups');
}
...
}
How do I get all of the groups, with a count of the members? I need the Group model, and a count of the users in the group.
If you're using Laravel 5.3, you can simply add withCount('relationship') as documented here: https://laravel.com/docs/5.3/eloquent-relationships#counting-related-models
Here's an example following your code:
$groups = Group::withCount('users')->get();
Now you can do this:
foreach($groups as $group) {
echo $group->user_count
}

Laravel hasManyThrough but must return only one array

I have these tables:
Entries table
---------------------------------
| id | blog_id | title |
---------------------------------
| 1 | 1 | 1st Entry |
---------------------------------
Blogs Table
-----------------
| id | name |
-----------------
| 1 | 1stBlog |
-----------------
Field Groups Table
-------------------------
| id | blog_id | name |
-------------------------
| 1 | 1 | Group1 |
-------------------------
Fields Table
---------------------------------
| id | field_group_id | name |
---------------------------------
| 1 | 1 | field_1 |
---------------------------------
Values Table
------------------------------------------
| id | field_id | entry_id | value |
------------------------------------------
| 1 | 1 | 1 | Hello World |
------------------------------------------
Now on my Models I've set up these relationships:
class Entry extends Model
{
public function blog()
{
return $this->belongsTo(Blog::class);
}
}
class Blog extends Model
{
public function entries()
{
return $this->hasMany(Entry::class);
}
public field_group()
{
return $this->hasOne(FieldGroup::class);
}
}
class FieldGroup extends Model
{
public function fields()
{
return $this->hasMany(Entry::class);
}
public function blog()
{
return $this->belongsTo(Blog::class);
}
}
class Field extends Model
{
public function group()
{
return $this->belongsTo(FieldGroup::class, 'field_group_id');
}
public function values()
{
// this method should get the values from the Values table per entry id
return $this->hasManyThrough(Value::class, Entry::class, 'id', 'entry_id');
}
}
class Value extends Model
{
public function field()
{
return $this->belongsTo(Field::class, 'field_id');
}
}
Using this query I can
$entry = Entry::with('blog.field_group.fields')->find(1)
I can get the entry, along with its blog, field groups and fields. I want to get the values associated with the entry too,
$entry = Entry::with('blog.field_group.fields.values')->find(1)
I am having trouble on which relationship to use. Any help is much appreciated. I just started using laravel.
Try it...
Replace ID by field_id:
return $this->hasManyThrough(Value::class, Entry::class, 'id', 'entry_id');
Like this:
return $this->hasManyThrough(Value::class, Entry::class, 'field_id', 'entry_id');
Because you are using the standard laravel column names you can simplify even more:
return $this->hasManyThrough(Value::class, Entry::class);
See in: https://laravel.com/docs/5.1/eloquent-relationships#has-many-through
I think you should use 'foreign_key' with 'hasMany' and 'hasOne'.
return $this->hasMany('Comment', 'foreign_key');
class Blog extends Model
{
public function entries()
{
return $this->hasMany(Entry::class, 'blog_id');
}
public field_group()
{
return $this->hasOne(FieldGroup::class, 'blog_id');
}
}
refer
http://laravel.com/docs/4.2/eloquent#one-to-many

Categories