Laravel framework eloquent relationship query - php

I have created relationship between 4 tables.
This are my models:
User
BusinessInfo
ElectrcityInfo
GasInfo
This are the primery keys that I am using in my tables:
user_id (to get login users data from BusinessInfo)
contract_id (This also exists in BusinessInfo I am use it to get data from the other two tables for specific records)
Now I want to get all login users data from BusinessInfo table and each BusinessInfo row has its own 1 row data from ElectricityInfo and GasInfo.
When I am use contract_id in model its give me relationship result null.
When it is on user_id its display only 1 ElectrcityInfo with all records.
Controller
$user = Auth::user();
$business = BusinessInfo::where('user_id', $user->id)->first();
$data = $business->electricity()->paginate(6);
return view('Pages.MySite', ['data' => $data]);
BusinessInfo Model
protected $primaryKey = 'contract_id';
public $table = "business_info";
protected $guarded = [];
public $timestamps = false;
public function electricity()
{
return $this->belongsTo('App\Models\ElectricityInfo', 'contract_id');
}
public function gas()
{
return $this->belongsTo('App\Models\GasInfo', 'contract_id');
}

You BusinessInfo model is missing the user relationship. Put this in your code:
public function user()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
Your query is not right
When it is on user_id its display only 1 ElectrcityInfo with all records.
This is because you use the first() method wich returns the first object from the collection. You should use this:
$businesses = BusinessInfo::where('user_id', $user->id)->get();
This will return all objects according to the query.
Now you can loop the $business array and access each information
foreach($businesses as $business)
{
$business->electricity()->first(); // this will return all your data from the BusinessInfo relation with the ElectricityInfo model
$business->gas()->first(); // this will return all your data from the BusinessInfo relation with the GasInfo model
}
For more info about the first() method and other methods click here
You also could take a look at the Eloquent: Relationships section to know more about how it works
In your view:
#foreach($businesses as $business)
{
{{$business->electricity()->first()}}
{{$business->gas()->first()}}
}
#endforeach

Related

How to retrieve all data from three tables according to groupby of second table's field value using Laravel eloquent query?

I have three models with some methods like
1.Employee Model
class Employee extends Model
{
protected $fillable = [
'employee_no','card_no','inactivedate', 'activedate', 'status',
];
public function office(){
return $this->hasOne(EmployeeOffice::class);
}
public function section(){
return $this->belongsTo('App\Hrm\Section');
}
}
2.EmployeeOffice Model
class EmployeeOffice extends Model
{
$fillable = ['employee_id','section_id','line_id','join_date','gross','confirm_date'];
public function employee(){
return $this->belongsTo(Employee::class);
}
public function section(){
return $this->belongsTo('App\Hrm\Section');
}
}
3.Section model....
class Section extends Model
{
protected $fillable = ['name','description','status'];
//
}
i need all inactive employee information according to the employee inactive date(from employee model) as well as their all office information from EmployeeOffice model and must be groupBy according to section_id which is (section_id as foreign key) available in EmployeeOffice model.
For that i have to go with some condition like ..
Employee::where('inactivedate','like','%'.$date.'%');
*And need all data from office and employee table
*need section name and grouped by as section name from section model
***please suggest me how can i solve this problem ***
Try this:
$data = Section::with(
array(
'employeeOffice' => function(
$query->with(
'employees' => function(
$query->where('employees.inactivatedate', 'like', '%'.$date.'%'
)
)
)
)
)
->get();
This should give you an array to every section_id. In this array are the employeeOffices (1:n-Relationship). The second query with with will fetch for each employeeOffice the employee who sits in it.
But if you defined the relationships right, this should do the trick to:
Section::with('EmployeeOffice.Employee')->get();
Nested Eager Loading
I have solved my problem by this...
if(Input::has('start') && Input::has('end')){
$start = Carbon::parse(Input::get('start'))->startOfDay();
$end = Carbon::parse(Input::get('end'))->endOfDay();
$start = $start->format('Y-m-d');
$end = $end->format('Y-m-d');
EmployeeOffice::query()->whereHas('employee',function ($query) use ($start,$end){
$query->whereBetween('inactivedate',[$start, $end])->where('status',0);
})->paginate()->groupBy('section_id');
}

Retrieving error on one to many relationship laravel

Been learning laravel for 4 days and im trying to fix this error for 2 hours and i cant still fix it. I can save on one to many relationship but i cant retrieve data i think there something wrong with the relationship. Im trying to retrieve posts on user using this line but im getting not empty results on users but empty result on posts. Same thing happening on categories and posts which is many to many relationship but i cant save on many to many.
$users = User::with('posts')->get();
ANd im getting an error when i use this the error is
Undefined property: Illuminate\Database\Eloquent\Collection::posts()
$users = User::where('user_id','=','2')->get();
$posts = $users->posts()->get();
Heres my user Model
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $primarykey = 'user_id';
protected $table = 'users';
public function posts(){
return $this->hasMany("App\Post");
}
}
Heres my posts Model
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $primarykey = 'id';
protected $table = 'posts';
public function post_validation_rules(){
return [
'post_title' => 'required|min:5|unique:posts',
'post_body' => 'required'
];
}
public function user(){
return $this->belongsTo("App\User");
}
public function categories(){
return $this->belongsToMany('App\Category', 'category_id', 'category_id');
}
}
Categories Post
class Category extends Model
{
protected $primarykey = 'category_id';
protected $table = 'categories';
public function posts(){
return $this->belongsToMany('App\Post', 'post_id', 'id');
}
}
Database
Posts Table
id
user_id
post_title
post_body
createad_date
updated_date
Users Table
user_id
username
email
pass
createad_date
updated_date
You can only call relations on a single object, not on an entire collection. $users is a collection of User objects.
If you want a single user object, use the first() function to get the first User object that matches.
$user = User::where('user_id','=','2')->first();
$posts = $user->posts;
Update:
To get the posts directly in the user object, you need to use the with function:
$user = User::with('posts')->where('user_id','=','2')->first();
Try to declare the field that have the relation between your tables then, for example:
$this->hasMany(App\Post::class, 'user_id', 'user_id');
Laravel is searching for a field id in User table but it does not exist. so with this way you will tell it that the field you look is user_id

Laravel 5 – get particular many to many relation based on model and related model ID

I've got Tag and Attendee Eloquent models, they are in many-to-many relation. Pivot table has also two more attributes – value_int and value_string. My Attendee model looks like this:
class Attendee extends Model
{
public $timestamps = false;
protected $fillable = [
'event_id'
];
public function tags() {
return $this->belongsToMany('App\Models\Tag', 'attendee_tag', 'attendee_id', 'tag_id')
->withPivot(['value_string', 'value_int']);
}
public function scoreTagValue($tag_id) {
return $this->tags->where('tag_id', '=', $tag_id)->first();
}
}
What I want is to obtain pivot values based on Attendee model and variable tag_id, so I've written scoreTagValue function, but it always returns null and I don't know why :( I'm calling it this way:
$attendee->scoreTagValue($tag_id). Thanks for your help :)
You need to access the relation, not the property:
public function scoreTagValue($tag_id) {
return $this->tags()->where('tag_id', '=', $tag_id)->first();
}
Also, according to the docs, withPivot() does not take an array, so:
->withPivot('value_string', 'value_int');

How to efficiently select only the IDs of a Belongs To Many relationship in Eloquent?

If I have a Users table and Tags table, and a pivot table for a Belongs To Many relationship, how do I use Eloquent to load only the IDs of the relation?
If I do User::with('tags'), this will do a join on the pivot table and also a join on the tags table. However, this is unnecessary and inefficient in my case, as I want to be able to only select the IDs of the tags from the pivot table, not the other columns in the Tags table. In other words, I only want it to do a single join from Users to Users_Tags.
Thank you.
OK, since #WereWolf's suggestions are not correct (1st will cause error, 3rd might be wrong if there are custom keys), here are the options for you, that not fetch related models.
Starting with the most obvious:
// for single model:
$user = User::first();
$user->tags()->allRelatedIds(); // select id from related table -> join
This is what you may use, but it is not the answer, since you want to eager load those ids.
That being said, you need to create another model for pivot table:
// UserTag model
protected $table = 'user_tag';
// this is not required, just to make it read-only
public static function boot()
{
parent::boot();
static::saving(function() {
return false;
}
}
// User model
public function tagsPivot()
{
return $this->hasMany('UserTag')->select('tag_id', 'user_id'); // appropriate keys here
}
public function getTagsIds()
{
return $this->tagsPivot->lists('tag_id');
}
// then you can do this:
$users = User::with('tagsPivot')->get(); // no join, select category_id from pivot table
foreach ($users as $user)
{
$user->getTagsIds();
}
.
You can also make some changes on the User model, depending on your liking:
// to be able to do this:
$users = User::with('tagsIds')->get();
foreach ($users as $user)
{
$user->tagsIds;
}
// User model
public function tagsIds()
{
return $this->hasMany('UserTag')->select('tag_id', 'user_id'); // appropriate keys here
}
public function getTagsIdsAttribute()
{
if ( ! array_key_exists('tagsIds', $this->relations)) $this->load('tagsIds');
return $this->getRelation('tagsIds')->lists('tag_id');
}
Give it a try (not tested):
$user = User::query();
$ids = $user->getRelation('tags')->getRelatedIds();
Or maybe something like this (but does some extra queries during the tags call):
$user = User::find(1);
$ids = $user->tags->fetch('id');
Update: (Another way)
$user = User::find(1);
$ids = array_fetch(DB::table($user->joiningTable('tag'))
->where($user->getForeignKey(), $user->getKey())
->get(), 'tag_id');

Laravel Object queries - 3 tables

I have three tables like this:
**Users**
id
**Posts**
id
user_id
**Favorites**
id
user_id
post_id
Currently, I made it so when I query my posts for display, it pulls all the related user data who created the post with that row which is great! But what I'm trying to do now is also add to see if the user Authorized (Logged in) has favorited the post (row) so I can display to that they already favorited it. I don't want to re-query for every post (i think its called the N+1 problem?). I'm using Laravel4
Post model
class Post extends Eloquent{
public function user(){
return $this->belongsTo('User');
}
User model
public function posts(){
return $this->hasMany('Post');
}
PostsController
public function index()
{
$posts = Post::with('user')->paginate(25);
return View::make('index', compact('posts'));
}
Step 1. Add favorites relationship in Post model.
public function favorites() {
return $this->hasMany('Favorite');
}
When querying the Model.
$auth_user_id = Auth::user()->id;
$posts = Post::with(array('user', 'favorites' => function($query) use ($auth_user_id){
$query->where('user_id', '=', $auth_user_id);
}))->get();
For more information refer to the eager load constraints,
http://laravel.com/docs/eloquent#eager-loading
Adding a many-to-many relationship using the favorites table as pivot would be one approach.
Add favorites relationship in User model:
public function favorites() {
return $this->belongsToMany('Post', 'favorites');
}
You should then be able to get all favorites by simply accessing
Auth::user()->favorites
To find whether the current post is a favorite, use
$isFavorite = Auth::user()->favorites->has($post->id);

Categories