Get Information of relation table using pivot table data - php

I am using Laravel 5.4. I have 2 tables destination and user and a pivot table destination_user.
destination table
---|------
id | name
---|------
1 | sth
user table
---|------
id | name
---|------
1 | sth
and finally Pivot table
--------------|--------
destination_id| user_id
--------------|--------
1 | 1
2 | 1
3 | 2
I created a model for pivot table named destinationUser.
My destination model looks like this:
<?php
namespace App\models;
use App\Models\User;
use App\Models\DestinationUser;
use App\Models\DestinationImage;
use Illuminate\Database\Eloquent\Model;
class Destination extends Model
{
protected $table = 'destinations';
public function user() {
return $this->belongsToMany('App\Models\User');
}
public function destinationUser() {
return $this->hasMany('App\Models\DestinationUser');
}
}
I want to get all the destinations with their respective user detail using pivot table. I have tried so far is this:
$destinations = $this->destination->with('user', 'destinationUser')
->whereHas('destinationUser', function($query) {
$query->where('user_id', user()->id);})
->paginate(20);
dd($destinations[0]->destinationUser); gives me destination id and user id but I want user detail. How can I achieve this. Thank You for your help

You need a many to many relationship:
class Destination extends Model
{
protected $table = 'destinations';
public function destinationUser() {
return $this->belongsToMany('App\User');
}
}
controller
$destinations = $this->destination->with('destinationUser', function($query) {
$query->where('user.id', user()->id);})
->paginate(20);

As I was searching for faster execution of queries, there was a wrong design of tables. There is more load and time of execution for 3 table with pivot rather than 2 tables without pivot. So, I figured it out and corrected.

Related

Searching collection records by relationship attributes

I have a game where people can get some items and equip them.
The items data is placed in two tables that are in relationship.
Items table contains all the possible items and user_items table contains the items that are owned by a player.
user_items table: id | user_id | item_id | is_equipped
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Item extends Model
{
use HasFactory;
public function userItems()
{
return $this->belongsTo(UserItem::class);
}
}
items table: id | item_name | body_part
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class UserItem extends Model
{
use HasFactory;
public function items()
{
return $this->hasOne(Item::class, 'id', 'item_id');
}
}
Now I am getting a collection of the user's items
$userItems = UserItem::where('user_id', Auth::id())->get(),
How do I search this collection by related table's columns? For example I want to get user $userItems where is_equipped == 1 and body_part == "head".
What you need is filter by the relation like this:
$userItems = UserItem::where('user_id', Auth::id())->whereHas('items', function($q)
{
$q->where('is_equipped', '=', 1);
})->get();
You can use the Eloquent's relationships to search the collection by related table's columns.
To get the user's items where is_equipped == 1 and body_part == "head", you can use the following code:
$userItems = UserItem::where('user_id', Auth::id())
->whereHas('items', function ($query) {
$query->where('is_equipped', 1)->where('body_part', 'head');
})->get();
This code first queries the user_items table for all items that belong to the user. Then, it uses the whereHas method to filter the results based on the related items table's columns. The closure passed to whereHas receives a $query variable that is a instance of Query Builder that you can use to filter the items table.
You could also use the join method to join the items table to the user_items table and then filter by the columns in the items table:
$userItems = UserItem::join('items', 'items.id', '=', 'user_items.item_id')
->where('user_items.user_id', Auth::id())
->where('items.is_equipped', 1)
->where('items.body_part', 'head')
->get();
This will give you a collection of user_items that are owned by the user and have is_equipped = 1 and body_part = 'head' in the items table.

Laravel 5.4 relationship 2 tables 3 id

I work with laravel 5.4, and I want receive information from my relations tables.
I have 3 tables in phpmyadmin
ATHLETES
ID
FIRST_NAME
LAST_NAME
TYPES
ID
NAME
SLUG
ATHLETES_TYPES
ID
TYPE_ID
ATHLETE_ID
I have 3 models
ATHLETE
TYPE
ATHLETEBYTYPE
How do I need to make the relations models to have name and slug from my table TYPES, with my id from my table athletes?
Thank you.
For this you just need 2 model file ATHLETE and TYPE and use many to many relation.and then you can use ATHLETES_TYPES table as pivot table.
for implement this :
first add this method to ATHLETE model file :
public function types()
{
return $this->belongsToMany(TYPE::class,'ATHLETES_TYPES','ATHLETE_ID','TYPE_ID');
}
secode add this method to TYPE model :
public function athletes()
{
return $this->belongsToMany(ATHLETE::class,'ATHLETES_TYPES','TYPE_ID','ATHLETE_ID');
}
and in last remove ID filed from ATHLETES_TYPES table.
done.
now if you have variable from ATHLETE type with $ATHLETE->types you can get types of than.
read more here :
https://laravel.com/docs/5.4/eloquent-relationships#many-to-many
Here are the relationships, buddy
In App/Athlete.php
class Athlete extends Model
{
public function types(){
return $this->belongsToMany('App\Type');
}
}
In App/Type.php
class Type extends Model
{
public function Athletes(){
return $this->belongsToMany('App\Athlete');
}
}

Laravel - remove single record from table without primary key

I have a table without 'primary ID', ex.
+---------+----------+------------+------------+
| user_id | point_id | created_at | updated_at |
+---------+----------+------------+------------+
And I have records:
1 ..| 200 | (date) | (date)
14 | 300 | (date) | (date)
1 ..| 200 | (date) | (date)
Now I want delete only one record to get:
1 ..| 200 | (date) | (date)
14 | 300 | (date) | (date)
I tryied:
UserPoint::where( 'point_id', $reqId )->where( 'user_id', $userId )->first()->delete();
But it always remove all record with this params ... Anyone can help?
EDIT: My UserPoint model
use Illuminate\Database\Eloquent\Model;
class UserPoint extends Model {
protected $table = 'point_user';
public function scopeUsed($query){
return $query->where('amount', '<', 0);
}
public function scopeEarned($query){
return $query->where('amount', '>', 0);
}
public function about(){
return $this->hasOne('\App\Point', 'id', 'point_id');
}
}
The way you are trying to achieve this deletion is somewhat wrong as it does not follow the rules of data integrity . Deleting a child table in your case would impose what we call an orphaned table.
However the correct way of deleting that record would be to first associate this table to its parent related table in this case as below:
Class User extends Model {
public function points() {
return $this->hasMany(UserPoint::class)
}
}
then in your UserPoint Class or Model you then need to map your relation.
class UserPoint extends Model {
protected $table = 'point_user';
// I have added this part
public function users() {
return $this->belongsTo(User::class)
}
public function scopeUsed($query){
return $query->where('amount', '<', 0);
}
public function scopeEarned($query){
return $query->where('amount', '>', 0);
}
public function about(){
return $this->hasOne('\App\Point', 'id', 'point_id');
}
}
This way you when deleting the Model or Item you can simply do the below:
// Inject your User in the constructor or function - lets say you names it User $user
$user->points->delete();
I suggest you also look at Eloquent's association and sync methods when working with relations this way you always know that the related Models are on sync and there re no orphaned children in the database which in Enterprise Design is a huge problem as accuracy and Data intergrity is everything .

laravel eloquent relationships queries

I have two tables 1)users
{ id, password }
2)expertise { id, expertise}
the relationship I have is
Models
Expertise.php
function User()
{
$this->hasOne('Expertise');
}
User.php
function Expertise()
{
$this->hasOne('User');
}
So how can I query using Eloquent to get the first 10 users with a certain expertise?
I want to join users.id = expertise.id and get the first 10 people with a specified expertise (Where clause).
Beginner to laravel, I've checked other sources but was not successful
Right now you are having a problem with the way that you modeled your data. If you have a one-to-one relationship the best practice to model it is to have one entity store the id of the other. The Laravel convention for this is to have a column named <model>_id:
Users
| id | password |
Expertises
| id | expertise | user_id |
Then in your models you can do this:
Models
Expertise.php
class Expertise extends Eloquent
{
public function User()
{
// because expertise has a column user_id
// expertise belongs to user
return $this->belongsTo('User');
}
}
User.php
class User extends Eloquent
{
public function Expertise()
{
// because expertise is the one with the column
// user_id, user has one expertise
return $this->hasOne('Expertise');
}
}
The Query
After you have all this set up, to be able to query the first 10 users with a certain expertise you can do this.
$users = User::whereHas('Expertise', function($q)
{
$q->where('expertise', '=', <expertise you are looking for>)
})
->take(10)
->get();
To get a further reading in querying relationships in Laravel please take a look at this:
Laravel - Querying Relationships
Keep in mind
keep in mind that the tables name must be plural, if not then you should specify the name of the table inside the model:
protected $table = 'expertise';

How to implement a self referencing (parent_id) model in Eloquent Orm

I have a User table and need to allow for users to have a parent user.
the table would have the fields:
id
parent_id
email
password
How would I define this self referencing relationship in Eloquent ORM?
I had some success like this, using your exact DB table.
User Model:
class User extends Eloquent {
protected $table = 'users';
public $timestamps = false;
public function parent()
{
return $this->belongsTo('User', 'parent_id');
}
public function children()
{
return $this->hasMany('User', 'parent_id');
}
}
and then I could use it in my code like this:
$user = User::find($id);
$parent = $user->parent()->first();
$children = $user->children()->get();
Give that a try and let me know how you get on!
I had a chain of self referencing contracts (a contract can be continued by another contract) and also needed self referencing. Each contract has zero or one previous and also zero or one next contract.
My data table looked like the following:
+------------------+
| contracts |
+------------------+
| id |
| next_contract_id |
+------------------+
To define the inverse of a relationship (previous contract) you have to inverse the related columns, that means setting
* foreign key column on the model table
* associated column on the parent table (which is the same table)
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Contract extends Model {
// The contract this contract followed
function previousContract()
{
// switching id and next_contract_id
return $this->belongsTo('App\Contract', 'id', 'next_contract_id');
}
// The contract that followed this contract
function nextContract()
{
return $this->belongsTo('App\Contract');
// this is the same as
// return $this->belongsTo('App\Contract', 'next_contract_id', 'id');
}
}
See http://laravel.com/docs/5.0/eloquent#one-to-one for further details.

Categories